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 15 BufferMixer::BufferMixer() { 16 } 17 18 BufferMixer::~BufferMixer() { 19 } 20 21 bool 22 BufferMixer::isBufferAvailable() { 23 return groupedBuffers[0] != NULL; 24 } 25 26 // Should only be called after checking with isBufferAvailable 27 BBuffer * 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 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 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 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