00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "common/scummsys.h"
00032 #include "common/endian.h"
00033
00034 #include "graphics/tinygl/zbuffer.h"
00035 #include "graphics/tinygl/zgl.h"
00036
00037 namespace TinyGL {
00038
00039
00040 void memset_s(void *adr, int val, int count) {
00041 int n, v;
00042 unsigned int *p;
00043 unsigned short *q;
00044
00045 p = (unsigned int *)adr;
00046 v = val | (val << 16);
00047
00048 n = count >> 3;
00049 for (int i = 0; i < n; i++) {
00050 p[0] = v;
00051 p[1] = v;
00052 p[2] = v;
00053 p[3] = v;
00054 p += 4;
00055 }
00056
00057 q = (unsigned short *) p;
00058 n = count & 7;
00059 for (int i = 0; i < n; i++)
00060 *q++ = val;
00061 }
00062
00063 void memset_l(void *adr, int val, int count) {
00064 int n, v;
00065 unsigned int *p;
00066
00067 p = (unsigned int *)adr;
00068 v = val;
00069 n = count >> 2;
00070 for (int i = 0; i < n; i++) {
00071 p[0] = v;
00072 p[1] = v;
00073 p[2] = v;
00074 p[3] = v;
00075 p += 4;
00076 }
00077
00078 n = count & 3;
00079 for (int i = 0; i < n; i++)
00080 *p++ = val;
00081 }
00082
00083 FrameBuffer::FrameBuffer(int width, int height, const Graphics::PixelBuffer &frame_buffer) : _depthWrite(true), _enableScissor(false) {
00084 int size;
00085
00086 this->xsize = width;
00087 this->ysize = height;
00088 this->cmode = frame_buffer.getFormat();
00089 this->pixelbytes = this->cmode.bytesPerPixel;
00090 this->linesize = (xsize * this->pixelbytes + 3) & ~3;
00091
00092 size = this->xsize * this->ysize * sizeof(unsigned int);
00093
00094 this->_zbuf = (unsigned int *)gl_malloc(size);
00095 memset(this->_zbuf, 0, size);
00096
00097 if (!frame_buffer) {
00098 byte *pixelBuffer = (byte *)gl_malloc(this->ysize * this->linesize);
00099 this->pbuf.set(this->cmode, pixelBuffer);
00100 this->frame_buffer_allocated = 1;
00101 } else {
00102 this->frame_buffer_allocated = 0;
00103 this->pbuf = frame_buffer;
00104 }
00105
00106 this->current_texture = NULL;
00107 this->shadow_mask_buf = NULL;
00108
00109 this->buffer.pbuf = this->pbuf.getRawBuffer();
00110 this->buffer.zbuf = this->_zbuf;
00111 _blendingEnabled = false;
00112 _alphaTestEnabled = false;
00113 _depthTestEnabled = false;
00114 _depthFunc = TGL_LESS;
00115 }
00116
00117 FrameBuffer::~FrameBuffer() {
00118 if (frame_buffer_allocated)
00119 pbuf.free();
00120 gl_free(_zbuf);
00121 }
00122
00123 Buffer *FrameBuffer::genOffscreenBuffer() {
00124 Buffer *buf = (Buffer *)gl_malloc(sizeof(Buffer));
00125 buf->pbuf = (byte *)gl_malloc(this->ysize * this->linesize);
00126 int size = this->xsize * this->ysize * sizeof(unsigned int);
00127 buf->zbuf = (unsigned int *)gl_malloc(size);
00128
00129 return buf;
00130 }
00131
00132 void FrameBuffer::delOffscreenBuffer(Buffer *buf) {
00133 gl_free(buf->pbuf);
00134 gl_free(buf->zbuf);
00135 gl_free(buf);
00136 }
00137
00138 void FrameBuffer::clear(int clearZ, int z, int clearColor, int r, int g, int b) {
00139 if (clearZ) {
00140 const uint8 *zc = (const uint8 *)&z;
00141 unsigned int i;
00142 for (i = 1; i < sizeof(z) && zc[0] == zc[i]; i++) { ; }
00143 if (i == sizeof(z)) {
00144
00145 memset(this->_zbuf, zc[0], sizeof(*this->_zbuf) * this->xsize * this->ysize);
00146 } else {
00147
00148 memset_l(this->_zbuf, z, this->xsize * this->ysize);
00149 }
00150 }
00151 if (clearColor) {
00152 byte *pp = this->pbuf.getRawBuffer();
00153 uint32 color = this->cmode.RGBToColor(r, g, b);
00154 const uint8 *colorc = (uint8 *)&color;
00155 unsigned int i;
00156 for (i = 1; i < sizeof(color) && colorc[0] == colorc[i]; i++) { ; }
00157 if (i == sizeof(color)) {
00158
00159 memset(pp, colorc[0], this->linesize * this->ysize);
00160 } else {
00161
00162 switch(this->pixelbytes) {
00163 case 2:
00164 memset_s(pp, color, this->xsize * this->ysize);
00165 break;
00166 case 4:
00167 memset_l(pp, color, this->xsize * this->ysize);
00168 break;
00169 default:
00170 error("Unsupported pixel size %i", this->pixelbytes);
00171 }
00172 }
00173 }
00174 }
00175
00176 void FrameBuffer::clearRegion(int x, int y, int w, int h, int clearZ, int z, int clearColor, int r, int g, int b) {
00177 if (clearZ) {
00178 int height = h;
00179 unsigned int *zbuf = this->_zbuf + (y * this->xsize);
00180 const uint8 *zc = (const uint8 *)&z;
00181 unsigned int i;
00182 for (i = 1; i < sizeof(z) && zc[0] == zc[i]; i++) { ; }
00183 if (i == sizeof(z)) {
00184
00185 while (height--) {
00186 memset(zbuf + x, zc[0], sizeof(*zbuf) * w);
00187 zbuf += this->xsize;
00188 }
00189 } else {
00190
00191 while (height--) {
00192 memset_l(zbuf + x, z, w);
00193 zbuf += this->xsize;
00194 }
00195 }
00196 }
00197 if (clearColor) {
00198 int height = h;
00199 byte *pp = this->pbuf.getRawBuffer() + y * this->linesize + x * this->pixelbytes;
00200 uint32 color = this->cmode.RGBToColor(r, g, b);
00201 const uint8 *colorc = (uint8 *)&color;
00202 unsigned int i;
00203 for (i = 1; i < sizeof(color) && colorc[0] == colorc[i]; i++) { ; }
00204 if (i == sizeof(color)) {
00205
00206 while (height--) {
00207 memset(pp, colorc[0], this->pixelbytes * w);
00208 pp += this->linesize;
00209 }
00210 } else {
00211
00212 while (height--) {
00213 switch(this->pixelbytes) {
00214 case 2:
00215 memset_s(pp, color, w);
00216 break;
00217 case 4:
00218 memset_l(pp, color, w);
00219 break;
00220 default:
00221 error("Unsupported pixel size %i", this->pixelbytes);
00222 }
00223 pp += this->linesize;
00224 }
00225 }
00226 }
00227 }
00228
00229 inline static void blitPixel(uint8 offset, unsigned int *from_z, unsigned int *to_z, unsigned int z_length, byte *from_color, byte *to_color, unsigned int color_length) {
00230 const unsigned int d = from_z[offset];
00231 if (d > to_z[offset]) {
00232 memcpy(to_color + offset, from_color + offset, color_length);
00233 memcpy(to_z + offset, &d, z_length);
00234 }
00235 }
00236
00237 void FrameBuffer::blitOffscreenBuffer(Buffer *buf) {
00238
00239 #define UNROLL_COUNT 16
00240 if (buf->used) {
00241 const int pixel_bytes = this->pixelbytes;
00242 const int unrolled_pixel_bytes = pixel_bytes * UNROLL_COUNT;
00243 byte *to = this->pbuf.getRawBuffer();
00244 byte *from = buf->pbuf;
00245 unsigned int *to_z = this->_zbuf;
00246 unsigned int *from_z = buf->zbuf;
00247 int count = this->xsize * this->ysize;
00248 while (count >= UNROLL_COUNT) {
00249 blitPixel(0x0, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00250 blitPixel(0x1, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00251 blitPixel(0x2, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00252 blitPixel(0x3, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00253 blitPixel(0x4, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00254 blitPixel(0x5, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00255 blitPixel(0x6, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00256 blitPixel(0x7, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00257 blitPixel(0x8, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00258 blitPixel(0x9, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00259 blitPixel(0xA, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00260 blitPixel(0xB, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00261 blitPixel(0xC, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00262 blitPixel(0xD, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00263 blitPixel(0xE, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00264 blitPixel(0xF, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00265 count -= UNROLL_COUNT;
00266 to += unrolled_pixel_bytes;
00267 from += unrolled_pixel_bytes;
00268 to_z += UNROLL_COUNT;
00269 }
00270 switch (count) {
00271 case 0xF: blitPixel(0xE, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00272 case 0xE: blitPixel(0xD, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00273 case 0xD: blitPixel(0xC, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00274 case 0xC: blitPixel(0xB, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00275 case 0xB: blitPixel(0xA, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00276 case 0xA: blitPixel(0x9, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00277 case 0x9: blitPixel(0x8, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00278 case 0x8: blitPixel(0x7, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00279 case 0x7: blitPixel(0x6, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00280 case 0x6: blitPixel(0x5, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00281 case 0x5: blitPixel(0x4, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00282 case 0x4: blitPixel(0x3, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00283 case 0x3: blitPixel(0x2, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00284 case 0x2: blitPixel(0x1, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00285 case 0x1: blitPixel(0x0, from_z, to_z, sizeof(int), from, to, pixel_bytes);
00286 case 0x0: break;
00287 }
00288 }
00289 #undef UNROLL_COUNT
00290 }
00291
00292 void FrameBuffer::selectOffscreenBuffer(Buffer *buf) {
00293 if (buf) {
00294 this->pbuf = buf->pbuf;
00295 this->_zbuf = buf->zbuf;
00296 buf->used = true;
00297 } else {
00298 this->pbuf = this->buffer.pbuf;
00299 this->_zbuf = this->buffer.zbuf;
00300 }
00301 }
00302
00303 void FrameBuffer::clearOffscreenBuffer(Buffer *buf) {
00304 memset(buf->pbuf, 0, this->ysize * this->linesize);
00305 memset(buf->zbuf, 0, this->ysize * this->xsize * sizeof(unsigned int));
00306 buf->used = false;
00307 }
00308
00309 void FrameBuffer::setTexture(const Graphics::PixelBuffer &texture) {
00310 current_texture = texture;
00311 }
00312
00313 }