00001 #ifndef _FRAMEBUF16_H_
00002 #define _FRAMEBUF16_H_
00003
00004 #include <stdio.h>
00005 #include <string.h>
00006
00007 #include "vuSimpleTypes.h"
00008 #include "Colour.h"
00009
00010 #define P2_16 65536 // 2^16
00011 #define P2_16_1 65535 // 2^16 - 1
00012 #define FB_WORD
00013
00014 typedef word fbtype;
00015
00020 template <int N>
00021 class FrameBuffer
00022 {
00023 friend class Colour<N>;
00024 public:
00025
00027 FrameBuffer() {m_Buffer = 0; }
00028
00030 FrameBuffer(int width, int height)
00031 {
00032 m_Buffer = 0;
00033 setSize(width, height);
00034 }
00035
00037 ~FrameBuffer()
00038 {
00039 freeBuffer();
00040 }
00041
00043 int getNumberOfChannels() { return N; }
00045 int getHeight() { return m_Height; }
00047 int getWidth() { return m_Width; }
00049 word* getData() { return m_Buffer; }
00050
00054 bool setSize(int width, int height)
00055 {
00056 freeBuffer();
00057 m_Buffer = new word[ width * height * N];
00058 if(!m_Buffer) return false;
00059 m_Width = width;
00060 m_Height = height;
00061 return true;
00062 }
00063
00065 bool freeBuffer()
00066 {
00067 if(m_Buffer) delete [] m_Buffer;
00068 m_Buffer = 0;
00069 m_Width = 0;
00070 m_Height = 0;
00071 return true;
00072 }
00073
00079 bool copy(FrameBuffer<N>& fb, int x, int y)
00080 {
00081 if ((!fb.m_Buffer) ||
00082 (N != fb.getNumberOfChannels()) ||
00083 (x < 0 || y < 0) ||
00084 (x + fb.m_Width>m_Width)||
00085 (y + fb.m_Height>m_Height)) return false;
00086
00087 int h = m_Height;
00088 int incdst = m_Width * N;
00089 int incsrc = fb.m_Width * N;
00090 word* src = fb.m_Buffer;
00091 word* dst = m_Buffer[y*m_Width + x];
00092 for(h=m_Height; h!=0; h--)
00093 {
00094 memcpy(dst,src,len);
00095 dst += incdst;
00096 src += incsrc;
00097 }
00098
00099 return true;
00100 }
00101
00106 bool add(FrameBuffer<N>& fb, int x, int y)
00107 {
00108 if ((!fb.m_Buffer) ||
00109 (x < 0 || y < 0) ||
00110 (x + fb.m_Width>m_Width)||
00111 (y + fb.m_Height>m_Height)) return false;
00112
00113 int incdst = (m_Width-fb.m_Width) * N;
00114 register word* src = fb.m_Buffer;
00115 register word* dst = &m_Buffer[y*m_Width + x];
00116 for(register int h=m_Height; h!=0; h--)
00117 {
00118 for(register int len = fb.m_Width * N;len!=0;len--)
00119 *(dst++) += *(src++);
00120 dst += incdst;
00121 }
00122 return true;
00123 }
00124
00125
00130 bool addColourWithMask(FrameBuffer<1>& fb, Colour<N>& colour, int x, int y)
00131 {
00132 if ((!fb.getData()) ||
00133 (x < 0 || y < 0) ||
00134 (x + fb.getWidth()>m_Width)||
00135 (y + fb.getHeight()>m_Height)) return false;
00136
00137 word col[] = {word(colour[0]*P2_16_1),
00138 word(colour[1]*P2_16_1),
00139 word(colour[2]*P2_16_1),
00140 word(colour[3]*P2_16_1)};
00141 int cpyh = fb.getHeight();
00142 int cpyw = fb.getWidth();
00143 int incdst = (m_Width-fb.getWidth()) * N;
00144 register word* src = fb.getData();
00145 register word* dst = &m_Buffer[(y*m_Width + x)*N];
00146 for(int h=cpyh; h!=0; h--) {
00147 for(register int len = cpyw; len!=0; len--) {
00148 register word *colval = col;
00149 register word alpha = (dword(*src)*col[3])>>16;
00150 for(register int comp = N-1; comp!=0; comp--, colval++) {
00151 *(dst++) += dword(alpha*(*colval))>>16;
00152 }
00153 *(dst++) += word(dword(*(src++))*(*colval)>>16);
00154 }
00155 dst += incdst;
00156 }
00157 return true;
00158 }
00159
00164 bool subColourWithMask(FrameBuffer<1>& fb, Colour<N>& colour, int x, int y)
00165 {
00166 if ((!fb.getData()) ||
00167 (x < 0 || y < 0) ||
00168 (x + fb.getWidth()>m_Width)||
00169 (y + fb.getHeight()>m_Height)) return false;
00170
00171 word col[] = {word(colour[0]*P2_16_1),
00172 word(colour[1]*P2_16_1),
00173 word(colour[2]*P2_16_1),
00174 word(colour[3]*P2_16_1)};
00175 int cpyh = fb.getHeight();
00176 int cpyw = fb.getWidth();
00177 int incdst = (m_Width-fb.getWidth()) * N;
00178 register word* src = fb.getData();
00179 register word* dst = &m_Buffer[(y*m_Width + x)*N];
00180 for(int h=cpyh; h!=0; h--) {
00181 for(register int len = cpyw; len!=0; len--) {
00182 register word *colval = col;
00183 for(register int comp = N-1; comp!=0; comp--, colval++) {
00184 *(dst++) -= word((dword(*src)*(*colval))>>16);
00185 }
00186 *(dst++) -= (dword(*(src++))*(*colval))>>16;
00187 }
00188 dst += incdst;
00189 }
00190 return true;
00191 }
00192
00197 bool addColourWithM1subM2(FrameBuffer<1>& m1, FrameBuffer<1>& m2,
00198 Colour<N>& colour, const int x, const int y)
00199 {
00200 if ((!m1.getData()) ||
00201 (!m2.getData()) ||
00202 ( m1.getWidth()!=m2.getWidth()) ||
00203 ( m1.getHeight()!=m2.getHeight()) ||
00204 (x < 0 || y < 0) ||
00205 (x + m1.getWidth()>m_Width)||
00206 (y + m1.getHeight()>m_Height)) return false;
00207
00208 word col[] = {word(colour[0]*P2_16_1),
00209 word(colour[1]*P2_16_1),
00210 word(colour[2]*P2_16_1),
00211 word(colour[3]*P2_16_1)};
00212
00213 if(N != 4) {
00214 int cpyh = m1.getHeight();
00215 int cpyw = m1.getWidth();
00216 int incdst = (m_Width-m1.getWidth()) * N;
00217 register word* datm1 = m1.getData();
00218 register word* datm2 = m2.getData();
00219 register word* dst = &m_Buffer[(y*m_Width + x)*N];
00220 for(int h=cpyh; h!=0; h--) {
00221 for(register int len = cpyw; len!=0; len--) {
00222 dword a = (dword((*datm1)-(*datm2))*col[N-1])>>16;
00223 for(int comp = 0; comp<N-1; comp++) {
00224 *(dst++) += (dword(a)*col[comp])>>16;
00225 }
00226 *(dst++) += a;
00227 datm1++; datm2++;
00228 }
00229 dst += incdst;
00230 }
00231 } else {
00232 int cpyh = m1.getHeight();
00233 int cpyw = m1.getWidth();
00234 int incdst = (m_Width-m1.getWidth()) * N;
00235 register word* datm1 = m1.getData();
00236 register word* datm2 = m2.getData();
00237 register word* dst = &m_Buffer[(y*m_Width + x)*N];
00238 for(int h=cpyh; h!=0; h--) {
00239 for(register int len = cpyw; len!=0; len--) {
00240 register dword a = (dword((*datm1)-(*datm2))*col[N-1])>>16;
00241 register word * colcomp = col;
00242 *(dst++) += word((a*(*(colcomp++)))>>16);
00243 *(dst++) += word((a*(*(colcomp++)))>>16);
00244 *(dst++) += word((a*(*(colcomp++)))>>16);
00245 *(dst++) += a;
00246 datm1++; datm2++;
00247 }
00248 dst += incdst;
00249 }
00250 }
00251 return true;
00252 }
00253
00255 bool blendOver(FrameBuffer<N>& fb, int x, int y)
00256 {
00257 if ((!fb.getData()) ||
00258 (x < 0 || y < 0) ||
00259 (x + fb.getWidth()>m_Width)||
00260 (y + fb.getHeight()>m_Height)) return false;
00261
00262 int cpyh = fb.getHeight();
00263 int cpyw = fb.getWidth();
00264 int incdst = (m_Width-fb.getWidth()) * N;
00265 register word* src = fb.getData();
00266 register word* dst = &m_Buffer[(y*m_Width + x)*N];
00267 for(int h=cpyh; h!=0; h--) {
00268 for(register int len = cpyw; len!=0; len--) {
00269 word a2 = P2_16_1-src[N-1];
00270 for(register int comp = 0;
00271 comp<N-1;
00272 comp++, dst++, src++) {
00273 *(dst) = word(((dword(*dst)*a2)>>16) + (*src));
00274 }
00275 dst++;
00276 src++;
00277 }
00278 dst += incdst;
00279 }
00280 return true;
00281 }
00282
00284 bool blendOver(FrameBuffer<N>& fb)
00285 {
00286 if ((!fb.getData()) ||
00287 (fb.getWidth()!=m_Width)||
00288 (fb.getHeight()!=m_Height)) return false;
00289 if(N!=4) {
00290 int cpylen = fb.getHeight()*fb.getWidth();
00291 register word* src = fb.getData();
00292 register word* dst = m_Buffer;
00293 for(register int len = cpylen; len!=0; len--) {
00294 word a2 = P2_16_1-src[N-1];
00295 for(register int comp = 0;
00296 comp<N-1;
00297 comp++, dst++, src++) {
00298 *(dst) = word(((dword(*dst)*a2)>>16) + (*src));
00299 }
00300 dst++;
00301 src++;
00302 }
00303 } else {
00304 int cpylen = fb.getHeight()*fb.getWidth();
00305 register word* src = fb.getData();
00306 register word* dst = m_Buffer;
00307 for(register int len = cpylen; len!=0; len--) {
00308 register word a2 = ~src[N-1];
00309
00310 *(dst++) = word((dword(dword(*dst)*a2)>>16) + (*src++));
00311 *(dst++) = word((dword(dword(*dst)*a2)>>16) + (*src++));
00312 *(dst++) = word((dword(dword(*dst)*a2)>>16) + (*src++));
00313
00314 dst++;
00315 src++;
00316 }
00317 }
00318 return true;
00319 }
00320
00324 bool blendUnder(FrameBuffer<N>& fb, int x, int y)
00325 {
00326 if ((!fb.getData()) ||
00327 (x < 0 || y < 0) ||
00328 (x + fb.getWidth()>m_Width)||
00329 (y + fb.getHeight()>m_Height)) return false;
00330
00331 int cpyh = fb.getHeight();
00332 int cpyw = fb.getWidth();
00333 int incdst = (m_Width-fb.getWidth()) * N;
00334 register word* src = fb.getData();
00335 register word* dst = &m_Buffer[(y*m_Width + x)*N];
00336 for(int h=cpyh; h!=0; h--) {
00337 for(register int len = cpyw; len!=0; len--) {
00338 word a = word((dword(src[N-1])*dst[N-1])>>16);
00339 word t = P2_16_1-dst[N-1];
00340 for(register int comp = 0;
00341 comp<N-1;
00342 comp++, dst++, src++) {
00343 *(dst) = word((dword(*dst)*t + dword(*src)*a)>>16);
00344 }
00345 *(dst++) *= P2_16_1-(*(src++));
00346 }
00347 dst += incdst;
00348 }
00349 return true;
00350 }
00351
00353 bool blendUnder(FrameBuffer<N>& fb)
00354 {
00355 if ((!fb.getData()) ||
00356 (fb.getWidth()!=m_Width)||
00357 (fb.getHeight()!=m_Height)) return false;
00358 if(N!=4) {
00359 int cpylen = fb.getHeight()*fb.getWidth();
00360 register word* src = fb.getData();
00361 register word* dst = m_Buffer;
00362 for(register int len = cpylen; len!=0; len--) {
00363 register dword t = dword(word(~dst[N-1]));
00364 for(register int comp = 0;
00365 comp<N-1;comp++) {
00366 *(dst++) += word(dword(*(src++))*t>>16);
00367 }
00368 dst++;
00369 src++;
00370 }
00371 } else {
00372 int cpylen = fb.getHeight()*fb.getWidth();
00373 register word* src = fb.getData();
00374 register word* dst = m_Buffer;
00375 for(register int len = cpylen; len!=0; len--) {
00376 register dword t = dword(word(~dst[N-1]));
00377 if(t == dword(~0) || src[N-1]==0) {
00378 dst += 4;
00379 src += 4;
00380 } else {
00381 *(dst++) += word(dword(*(src++))*t>>16);
00382 *(dst++) += word(dword(*(src++))*t>>16);
00383 *(dst++) += word(dword(*(src++))*t>>16);
00384
00385 *(dst++) += word(dword(*(src++))*t>>16);
00386 }
00387 }
00388 }
00389 return true;
00390 }
00391
00393 bool clear(const Colour<N> colour)
00394 {
00395 if(m_Buffer == 0) return false;
00396 word col[] = {word(colour[0]*P2_16_1),
00397 word(colour[1]*P2_16_1),
00398 word(colour[2]*P2_16_1),
00399 word(colour[3]*P2_16_1)};
00400 if(col[0]==0 && col[0]==col[1] && col[0]==col[2] && col[0]==col[3]) {
00401 memset(m_Buffer,0,sizeof(word)*N*m_Width*m_Height);
00402 } else {
00403 word *dst = m_Buffer;
00404 for(register int i = m_Width*m_Height; i!=0; i--) {
00405 memcpy(dst,col,sizeof(word)*N);
00406 dst += N;
00407 }
00408 }
00409 return true;
00410 }
00411
00413 bool print()
00414 {
00415 if(m_Buffer == 0) return false;
00416 word *buf = m_Buffer;
00417 for(int i = 0; i<m_Height; i++) {
00418 for(int j = 0;j<m_Width; j++) {
00419 printf("[%3i,%3i] = (%i", j, i, *(buf++));
00420 for(int c = 1; c<N; c++, buf++){
00421 printf(", %i", *buf);
00422 }
00423 printf(")\n");
00424 }
00425 putchar('\n');
00426 }
00427 return true;
00428 }
00429
00430 protected:
00431 int m_Width, m_Height;
00432 word *m_Buffer;
00433 };
00434
00435
00437 typedef FrameBuffer<1> AlphaMask;
00441 typedef FrameBuffer<4> RGBABuffer;
00442
00443 #endif