1 /*
2 * Copyright (C) 2010 David McPaul
3 *
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6
7 // This class merges buffers together
8 // Merge is called everytime a primary buffer needs to be passed downstream
9 // This should allow different framerates to be handled by buffering slower
10 // buffer producers and discarding buffers from faster producers
11 // TODO ColorConversion
12
13 #include "BufferMixer.h"
14
BufferMixer()15 BufferMixer::BufferMixer() {
16 }
17
~BufferMixer()18 BufferMixer::~BufferMixer() {
19 }
20
21 bool
isBufferAvailable()22 BufferMixer::isBufferAvailable() {
23 return groupedBuffers[0] != NULL;
24 }
25
26 // Should only be called after checking with isBufferAvailable
27 BBuffer *
GetOutputBuffer()28 BufferMixer::GetOutputBuffer() {
29 // Do the merging of all buffers in the groupedBuffers map
30 // into the primary buffer and return that buffer.
31 // The primary buffer is removed;
32
33 BBuffer *outputBuffer = groupedBuffers[0];
34 groupedBuffers[0] = NULL;
35
36 std::map<int32, BBuffer*>::iterator each;
37
38 for (each=groupedBuffers.begin(); each != groupedBuffers.end(); each++) {
39 if (each->second != outputBuffer) {
40 if (each->second != NULL) {
41 Merge(each->second, outputBuffer);
42 }
43 }
44 }
45
46 return outputBuffer;
47 }
48
49 #define ALPHABLEND(source, destination, alpha) (((destination) * (256 - (alpha)) + (source) * (alpha)) >> 8)
50
51 void
Merge(BBuffer * input,BBuffer * output)52 BufferMixer::Merge(BBuffer *input, BBuffer *output) {
53 // Currently only deals with RGBA32
54
55 uint8 *source = (uint8 *)input->Data();
56 uint8 *destination = (uint8 *)output->Data();
57 uint32 size = input->Header()->size_used / 4;
58 uint8 alpha = 0;
59 uint8 c1, c2, c3;
60
61 for (uint32 i=0; i<size; i++) {
62 c1 = *source++;
63 c2 = *source++;
64 c3 = *source++;
65 alpha = *source++;
66 destination[0] = ALPHABLEND(c1, destination[0], alpha);
67 destination[1] = ALPHABLEND(c2, destination[1], alpha);
68 destination[2] = ALPHABLEND(c3, destination[2], alpha);
69 destination[3] = 0x00;
70 destination += 4;
71 }
72 }
73
74 void
AddBuffer(int32 id,BBuffer * buffer,bool isPrimary)75 BufferMixer::AddBuffer(int32 id, BBuffer *buffer, bool isPrimary) {
76 BBuffer *oldBuffer;
77
78 if (isPrimary) {
79 oldBuffer = groupedBuffers[0];
80 groupedBuffers[0] = buffer;
81 } else {
82 oldBuffer = groupedBuffers[id];
83 groupedBuffers[id] = buffer;
84 }
85
86 if (oldBuffer != NULL) {
87 oldBuffer->Recycle();
88 }
89 }
90
91 void
RemoveBuffer(int32 id)92 BufferMixer::RemoveBuffer(int32 id) {
93 BBuffer *oldBuffer;
94
95 if (uint32(id) < groupedBuffers.size()) {
96 oldBuffer = groupedBuffers[id];
97 groupedBuffers[id] = NULL;
98
99 if (oldBuffer != NULL) {
100 oldBuffer->Recycle();
101 }
102 }
103 }
104