10fe9fd36SDavid McPaul/*
20fe9fd36SDavid McPaul * Copyright (C) 2010 David McPaul
30fe9fd36SDavid McPaul *
40fe9fd36SDavid McPaul * All rights reserved. Distributed under the terms of the MIT License.
50fe9fd36SDavid McPaul */
60fe9fd36SDavid McPaul
70fe9fd36SDavid McPaul// This class merges buffers together
80fe9fd36SDavid McPaul// Merge is called everytime a primary buffer needs to be passed downstream
90fe9fd36SDavid McPaul// This should allow different framerates to be handled by buffering slower
100fe9fd36SDavid McPaul// buffer producers and discarding buffers from faster producers
110fe9fd36SDavid McPaul// TODO ColorConversion
120fe9fd36SDavid McPaul
130fe9fd36SDavid McPaul#include "BufferMixer.h"
140fe9fd36SDavid McPaul
150fe9fd36SDavid McPaulBufferMixer::BufferMixer() {
160fe9fd36SDavid McPaul}
170fe9fd36SDavid McPaul
180fe9fd36SDavid McPaulBufferMixer::~BufferMixer() {
190fe9fd36SDavid McPaul}
200fe9fd36SDavid McPaul
210fe9fd36SDavid McPaulbool
220fe9fd36SDavid McPaulBufferMixer::isBufferAvailable() {
230fe9fd36SDavid McPaul	return groupedBuffers[0] != NULL;
240fe9fd36SDavid McPaul}
250fe9fd36SDavid McPaul
260fe9fd36SDavid McPaul// Should only be called after checking with isBufferAvailable
270fe9fd36SDavid McPaulBBuffer *
280fe9fd36SDavid McPaulBufferMixer::GetOutputBuffer() {
290fe9fd36SDavid McPaul	// Do the merging of all buffers in the groupedBuffers map
300fe9fd36SDavid McPaul	// into the primary buffer and return that buffer.
310fe9fd36SDavid McPaul	// The primary buffer is removed;
320fe9fd36SDavid McPaul
330fe9fd36SDavid McPaul	BBuffer *outputBuffer = groupedBuffers[0];
340fe9fd36SDavid McPaul	groupedBuffers[0] = NULL;
350fe9fd36SDavid McPaul
36c436ab31SDavid McPaul	std::map<int32, BBuffer*>::iterator each;
370fe9fd36SDavid McPaul
380fe9fd36SDavid McPaul	for (each=groupedBuffers.begin(); each != groupedBuffers.end(); each++) {
390fe9fd36SDavid McPaul		if (each->second != outputBuffer) {
400fe9fd36SDavid McPaul			if (each->second != NULL) {
410fe9fd36SDavid McPaul				Merge(each->second, outputBuffer);
420fe9fd36SDavid McPaul			}
430fe9fd36SDavid McPaul		}
440fe9fd36SDavid McPaul	}
450fe9fd36SDavid McPaul
460fe9fd36SDavid McPaul	return outputBuffer;
470fe9fd36SDavid McPaul}
480fe9fd36SDavid McPaul
490fe9fd36SDavid McPaul#define ALPHABLEND(source, destination, alpha) (((destination) * (256 - (alpha)) + (source) * (alpha)) >> 8)
500fe9fd36SDavid McPaul
510fe9fd36SDavid McPaulvoid
520fe9fd36SDavid McPaulBufferMixer::Merge(BBuffer *input, BBuffer *output) {
530fe9fd36SDavid McPaul	// Currently only deals with RGBA32
540fe9fd36SDavid McPaul
550fe9fd36SDavid McPaul	uint8 *source = (uint8 *)input->Data();
560fe9fd36SDavid McPaul	uint8 *destination = (uint8 *)output->Data();
570fe9fd36SDavid McPaul	uint32 size = input->Header()->size_used / 4;
580fe9fd36SDavid McPaul	uint8 alpha = 0;
590fe9fd36SDavid McPaul	uint8 c1, c2, c3;
60127a93c2SDario Casalinuovo
610fe9fd36SDavid McPaul	for (uint32 i=0; i<size; i++) {
620fe9fd36SDavid McPaul		c1    = *source++;
630fe9fd36SDavid McPaul		c2    = *source++;
640fe9fd36SDavid McPaul		c3    = *source++;
65a3d9c49aSDavid McPaul		alpha = *source++;
6618e199bdSDario Casalinuovo		destination[0] = ALPHABLEND(c1, destination[0], alpha);
6718e199bdSDario Casalinuovo		destination[1] = ALPHABLEND(c2, destination[1], alpha);
6818e199bdSDario Casalinuovo		destination[2] = ALPHABLEND(c3, destination[2], alpha);
6918e199bdSDario Casalinuovo		destination[3] = 0x00;
70127a93c2SDario Casalinuovo		destination += 4;
710fe9fd36SDavid McPaul	}
720fe9fd36SDavid McPaul}
730fe9fd36SDavid McPaul
740fe9fd36SDavid McPaulvoid
750fe9fd36SDavid McPaulBufferMixer::AddBuffer(int32 id, BBuffer *buffer, bool isPrimary) {
760fe9fd36SDavid McPaul	BBuffer *oldBuffer;
770fe9fd36SDavid McPaul
780fe9fd36SDavid McPaul	if (isPrimary) {
790fe9fd36SDavid McPaul		oldBuffer = groupedBuffers[0];
800fe9fd36SDavid McPaul		groupedBuffers[0] = buffer;
810fe9fd36SDavid McPaul	} else {
820fe9fd36SDavid McPaul		oldBuffer = groupedBuffers[id];
830fe9fd36SDavid McPaul		groupedBuffers[id] = buffer;
840fe9fd36SDavid McPaul	}
850fe9fd36SDavid McPaul
860fe9fd36SDavid McPaul	if (oldBuffer != NULL) {
870fe9fd36SDavid McPaul		oldBuffer->Recycle();
880fe9fd36SDavid McPaul	}
890fe9fd36SDavid McPaul}
90c436ab31SDavid McPaul
91c436ab31SDavid McPaulvoid
92c436ab31SDavid McPaulBufferMixer::RemoveBuffer(int32 id) {
93c436ab31SDavid McPaul	BBuffer *oldBuffer;
94c436ab31SDavid McPaul
95127a93c2SDario Casalinuovo	if (uint32(id) < groupedBuffers.size()) {
96c436ab31SDavid McPaul		oldBuffer = groupedBuffers[id];
97c436ab31SDavid McPaul		groupedBuffers[id] = NULL;
98c436ab31SDavid McPaul
99c436ab31SDavid McPaul		if (oldBuffer != NULL) {
100c436ab31SDavid McPaul			oldBuffer->Recycle();
101c436ab31SDavid McPaul		}
102c436ab31SDavid McPaul	}
103c436ab31SDavid McPaul}