ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

zdirtyrect.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 /*
00024  * This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
00025  * which is licensed under the zlib-license (see LICENSE).
00026  * It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
00027  */
00028 
00029 #include "graphics/tinygl/zdirtyrect.h"
00030 #include "graphics/tinygl/zgl.h"
00031 #include "graphics/tinygl/gl.h"
00032 #include "common/debug.h"
00033 #include "common/math.h"
00034 
00035 namespace TinyGL {
00036 
00037 void tglIssueDrawCall(Graphics::DrawCall *drawCall) {
00038     TinyGL::GLContext *c = TinyGL::gl_get_context();
00039     if (c->_enableDirtyRectangles && drawCall->getDirtyRegion().isEmpty())
00040         return;
00041     c->_drawCallsQueue.push_back(drawCall);
00042 }
00043 
00044 #if TGL_DIRTY_RECT_SHOW
00045 static void tglDrawRectangle(Common::Rect rect, int r, int g, int b) {
00046     TinyGL::GLContext *c = TinyGL::gl_get_context();
00047 
00048     if (rect.left < 0)
00049         rect.left = 0;
00050     if (rect.right >= c->fb->xsize)     
00051         rect.right = c->fb->xsize - 1;
00052     if (rect.top < 0)
00053         rect.top = 0;
00054     if (rect.bottom >= c->fb->ysize) 
00055         rect.bottom = c->fb->ysize - 1;
00056 
00057     for(int x = rect.left; x < rect.right; x++) {
00058         c->fb->writePixel(rect.top * c->fb->xsize + x, 255, r, g, b);
00059         c->fb->writePixel((rect.bottom - 1) * c->fb->xsize + x, 255, r, g, b);
00060     }
00061     for(int y = rect.top; y < rect.bottom; y++) {
00062         c->fb->writePixel(y * c->fb->xsize + rect.left, 255, r, g, b);
00063         c->fb->writePixel(y * c->fb->xsize + rect.right - 1, 255, r, g, b);
00064     }
00065 }
00066 #endif
00067 
00068 struct DirtyRectangle {
00069     Common::Rect rectangle;
00070     int r, g, b;
00071 
00072     DirtyRectangle() { }
00073     DirtyRectangle(Common::Rect rect, int red, int green, int blue) {
00074         this->rectangle = rect;
00075         this->r = red;
00076         this->g = green;
00077         this->b = blue;
00078     }
00079 };
00080 
00081 
00082 void tglDisposeResources(TinyGL::GLContext *c) {
00083     // Dispose textures and resources.
00084     bool allDisposed = true;
00085     do {
00086         allDisposed = true;
00087         for (int i = 0; i < TEXTURE_HASH_TABLE_SIZE; i++) {
00088             TinyGL::GLTexture *t = c->shared_state.texture_hash_table[i];
00089             while (t) {
00090                 if (t->disposed) {
00091                     TinyGL::free_texture(c, t);
00092                     allDisposed = false;
00093                     break;
00094                 }
00095                 t = t->next;
00096             }
00097         }
00098 
00099     } while (allDisposed == false);
00100 
00101     Graphics::Internal::tglCleanupImages();
00102 }
00103 
00104 void tglDisposeDrawCallLists(TinyGL::GLContext *c) {
00105     typedef Common::List<Graphics::DrawCall *>::const_iterator DrawCallIterator;
00106     for (DrawCallIterator it = c->_previousFrameDrawCallsQueue.begin(); it != c->_previousFrameDrawCallsQueue.end(); ++it) {
00107         delete *it;
00108     }
00109     c->_previousFrameDrawCallsQueue.clear();
00110     for (DrawCallIterator it = c->_drawCallsQueue.begin(); it != c->_drawCallsQueue.end(); ++it) {
00111         delete *it;
00112     }
00113     c->_drawCallsQueue.clear();
00114 }
00115 
00116 static inline void _appendDirtyRectangle(const Graphics::DrawCall &call, Common::List<DirtyRectangle> &rectangles, int r, int g, int b) {
00117     Common::Rect dirty_region = call.getDirtyRegion();
00118     if (rectangles.empty() || dirty_region != (*rectangles.end()).rectangle)
00119         rectangles.push_back(DirtyRectangle(dirty_region, r, g, b));
00120 }
00121 
00122 static void tglPresentBufferDirtyRects(TinyGL::GLContext *c) {
00123     typedef Common::List<Graphics::DrawCall *>::const_iterator DrawCallIterator;
00124     typedef Common::List<TinyGL::DirtyRectangle>::iterator RectangleIterator;
00125 
00126     Common::List<DirtyRectangle> rectangles;
00127 
00128     DrawCallIterator itFrame = c->_drawCallsQueue.begin();
00129     DrawCallIterator endFrame = c->_drawCallsQueue.end();
00130     DrawCallIterator itPrevFrame = c->_previousFrameDrawCallsQueue.begin();
00131     DrawCallIterator endPrevFrame = c->_previousFrameDrawCallsQueue.end();
00132 
00133     // Compare draw calls.
00134     for ( ; itPrevFrame != endPrevFrame && itFrame != endFrame;
00135         ++itPrevFrame, ++itFrame) {
00136             const Graphics::DrawCall &currentCall = **itFrame;
00137             const Graphics::DrawCall &previousCall = **itPrevFrame;
00138 
00139             if (previousCall != currentCall) {
00140                 _appendDirtyRectangle(previousCall, rectangles, 255, 255, 255);
00141                 _appendDirtyRectangle(currentCall, rectangles, 255, 0, 0);
00142             }
00143     }
00144 
00145     for ( ; itPrevFrame != endPrevFrame; ++itPrevFrame) {
00146         _appendDirtyRectangle(**itPrevFrame, rectangles, 255, 255, 255);
00147     }
00148 
00149     for ( ; itFrame != endFrame; ++itFrame) {
00150         _appendDirtyRectangle(**itFrame, rectangles, 255, 0, 0);
00151     }
00152 
00153     // This loop increases outer rectangle coordinates to favor merging of adjacent rectangles.
00154     for (RectangleIterator it = rectangles.begin(); it != rectangles.end(); ++it) {
00155         (*it).rectangle.right++;
00156         (*it).rectangle.bottom++;
00157     }
00158 
00159     // Merge coalesce dirty rects.
00160     bool restartMerge;
00161     do {
00162         restartMerge = false;
00163         for (RectangleIterator it1 = rectangles.begin(); it1 != rectangles.end(); ++it1) {
00164             for (RectangleIterator it2 = rectangles.begin(); it2 != rectangles.end();) {
00165                 if (it1 != it2) {
00166                     if ((*it1).rectangle.intersects((*it2).rectangle)) {
00167                         (*it1).rectangle.extend((*it2).rectangle);
00168                         it2 = rectangles.erase(it2);
00169                         restartMerge = true;
00170                     } else {
00171                         ++it2;
00172                     }
00173                 } else {
00174                     ++it2;
00175                 }
00176             }
00177         }
00178     } while(restartMerge);
00179 
00180     for (RectangleIterator it1 = rectangles.begin(); it1 != rectangles.end(); ++it1) {
00181         RectangleIterator it2 = it1;
00182         it2++;
00183         while (it2 != rectangles.end()) {
00184             if ((*it1).rectangle.contains((*it2).rectangle)) {
00185                 it2 = rectangles.erase(it2);
00186             } else {
00187                 ++it2;
00188             }
00189         }
00190     }
00191 
00192     for (RectangleIterator it1 = rectangles.begin(); it1 != rectangles.end(); ++it1) {
00193         (*it1).rectangle.clip(c->renderRect);
00194     }
00195 
00196     if (!rectangles.empty()) {
00197         // Execute draw calls.
00198         for (DrawCallIterator it = c->_drawCallsQueue.begin(); it != c->_drawCallsQueue.end(); ++it) {
00199             Common::Rect drawCallRegion = (*it)->getDirtyRegion();
00200             for (RectangleIterator itRect = rectangles.begin(); itRect != rectangles.end(); ++itRect) {
00201                 Common::Rect dirtyRegion = (*itRect).rectangle;
00202                 if (dirtyRegion.intersects(drawCallRegion)) {
00203                     (*it)->execute(dirtyRegion, true);
00204                 }
00205             }
00206         }
00207 #if TGL_DIRTY_RECT_SHOW
00208         // Draw debug rectangles.
00209         // Note: white rectangles are rectangle that contained other rectangles
00210         // blue rectangles are rectangle merged from other rectangles
00211         // red rectangles are original dirty rects
00212 
00213         bool blendingEnabled = c->fb->isBlendingEnabled();
00214         bool alphaTestEnabled = c->fb->isAlphaTestEnabled();
00215         c->fb->enableBlending(false);
00216         c->fb->enableAlphaTest(false);
00217 
00218         for (RectangleIterator it = rectangles.begin(); it != rectangles.end(); ++it) {
00219             tglDrawRectangle((*it).rectangle, (*it).r, (*it).g, (*it).b);
00220         }
00221 
00222         c->fb->enableBlending(blendingEnabled);
00223         c->fb->enableAlphaTest(alphaTestEnabled);
00224 #endif
00225     }
00226 
00227     // Dispose not necessary draw calls.
00228     for (DrawCallIterator it = c->_previousFrameDrawCallsQueue.begin(); it != c->_previousFrameDrawCallsQueue.end(); ++it) {
00229         delete *it;
00230     }
00231 
00232     c->_previousFrameDrawCallsQueue = c->_drawCallsQueue;
00233     c->_drawCallsQueue.clear();
00234 
00235 
00236     tglDisposeResources(c);
00237 
00238     c->_currentAllocatorIndex = (c->_currentAllocatorIndex + 1) & 0x1;
00239     c->_drawCallAllocator[c->_currentAllocatorIndex].reset();
00240 }
00241 
00242 static void tglPresentBufferSimple(TinyGL::GLContext *c) {
00243     typedef Common::List<Graphics::DrawCall *>::const_iterator DrawCallIterator;
00244 
00245     for (DrawCallIterator it = c->_drawCallsQueue.begin(); it != c->_drawCallsQueue.end(); ++it) {
00246         (*it)->execute(true);
00247         delete *it;
00248     }
00249 
00250     c->_drawCallsQueue.clear();
00251 
00252     tglDisposeResources(c);
00253 
00254     c->_drawCallAllocator[c->_currentAllocatorIndex].reset();
00255 }
00256 
00257 void tglPresentBuffer() {
00258     TinyGL::GLContext *c = TinyGL::gl_get_context();
00259     if (c->_enableDirtyRectangles) {
00260         tglPresentBufferDirtyRects(c);
00261     } else {
00262         tglPresentBufferSimple(c);
00263     }
00264 }
00265 
00266 } // end of namespace TinyGL
00267 
00268 namespace Graphics {
00269 
00270 bool DrawCall::operator==(const DrawCall &other) const {
00271     if (_type == other._type) {
00272         switch (_type) {
00273         case DrawCall_Rasterization:
00274             return *(const RasterizationDrawCall *)this == (const RasterizationDrawCall &)other;
00275             break;
00276         case DrawCall_Blitting:
00277             return *(const BlittingDrawCall *)this == (const BlittingDrawCall &)other;
00278             break;
00279         case DrawCall_Clear:
00280             return *(const ClearBufferDrawCall *)this == (const ClearBufferDrawCall &)other;
00281             break;
00282         default:
00283             return false;
00284         }
00285     } else {
00286         return false;
00287     }
00288 }
00289 
00290 RasterizationDrawCall::RasterizationDrawCall() : DrawCall(DrawCall_Rasterization) {
00291     TinyGL::GLContext *c = TinyGL::gl_get_context();
00292     _vertexCount = c->vertex_cnt;
00293     _vertex = (TinyGL::GLVertex *) ::Internal::allocateFrame(_vertexCount * sizeof(TinyGL::GLVertex));
00294     _drawTriangleFront = c->draw_triangle_front;
00295     _drawTriangleBack = c->draw_triangle_back;
00296     memcpy(_vertex, c->vertex, sizeof(TinyGL::GLVertex) * _vertexCount);
00297     _state = captureState();
00298     if (c->_enableDirtyRectangles) {
00299         computeDirtyRegion();
00300     }
00301 }
00302 
00303 void RasterizationDrawCall::computeDirtyRegion() {
00304     int clip_code = 0xf;
00305 
00306     for (int i = 0; i < _vertexCount; i++) {
00307         clip_code &= _vertex[i].clip_code;
00308     }
00309 
00310     if (!clip_code) {
00311         TinyGL::GLContext *c = TinyGL::gl_get_context();
00312         int xmax = c->fb->xsize - 1;
00313         int ymax = c->fb->ysize - 1;
00314         int left = xmax, right = 0, top = ymax, bottom = 0;
00315         for (int i = 0; i < _vertexCount; i++) {
00316             TinyGL::GLVertex *v = &_vertex[i];
00317             if (v->clip_code)
00318                 gl_transform_to_viewport(c, v);
00319             left =   MIN(left,   v->clip_code & 0x1 ?    0 : v->zp.x);
00320             right =  MAX(right,  v->clip_code & 0x2 ? xmax : v->zp.x);
00321             bottom = MAX(bottom, v->clip_code & 0x4 ? ymax : v->zp.y);
00322             top =    MIN(top,    v->clip_code & 0x8 ?    0 : v->zp.y);
00323         }
00324         // Note: clipping outside of Rect is required despite above clip_code checks,
00325         // as vertices far on the Z axis will overflow X and/or Y coordinates.
00326         // This happens in EMI intro, for example.
00327         _dirtyRegion = Common::Rect(
00328             MAX(0, left),
00329             MAX(0, top),
00330             MIN(right, xmax) + 1,
00331             MIN(bottom, ymax) + 1
00332         );
00333     }
00334 }
00335 
00336 void RasterizationDrawCall::execute(bool restoreState) const {
00337     TinyGL::GLContext *c = TinyGL::gl_get_context();
00338 
00339     RasterizationDrawCall::RasterizationState backupState;
00340     if (restoreState) {
00341         backupState = captureState();
00342     }
00343     applyState(_state);
00344 
00345     TinyGL::GLVertex *prevVertex = c->vertex;
00346     int prevVertexCount = c->vertex_cnt;
00347 
00348     c->vertex = _vertex;
00349     c->vertex_cnt = _vertexCount;
00350     c->draw_triangle_front = (TinyGL::gl_draw_triangle_func)_drawTriangleFront;
00351     c->draw_triangle_back = (TinyGL::gl_draw_triangle_func)_drawTriangleBack;
00352 
00353     int n = c->vertex_n;
00354     int cnt = c->vertex_cnt;
00355 
00356     switch (c->begin_type) {
00357     case TGL_POINTS:
00358         for(int i = 0; i < cnt; i++) {
00359             gl_draw_point(c, &c->vertex[i]);
00360         }
00361         break;
00362     case TGL_LINES:
00363         for(int i = 0; i < cnt / 2; i++) {
00364             gl_draw_line(c, &c->vertex[i * 2], &c->vertex[i * 2 + 1]);
00365         }
00366         break;
00367     case TGL_LINE_LOOP:
00368         gl_draw_line(c, &c->vertex[cnt - 1], &c->vertex[0]);
00369         // Fall through...
00370     case TGL_LINE_STRIP:
00371         for(int i = 0; i < cnt - 1; i++) {
00372             gl_draw_line(c, &c->vertex[i], &c->vertex[i + 1]);
00373         }
00374         break;
00375     case TGL_TRIANGLES:
00376         for(int i = 0; i < cnt; i += 3) {
00377             gl_draw_triangle(c, &c->vertex[i], &c->vertex[i + 1], &c->vertex[i + 2]);
00378         }
00379         break;
00380     case TGL_TRIANGLE_STRIP:
00381         while (cnt >= 3) {
00382             // needed to respect triangle orientation
00383             switch (cnt & 1) {
00384             case 0:
00385                 gl_draw_triangle(c, &c->vertex[2], &c->vertex[1], &c->vertex[0]);
00386                 break;
00387             case 1:
00388                 gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
00389                 break;
00390             }
00391             cnt--;
00392             c->vertex++;
00393         }
00394         break;
00395     case TGL_TRIANGLE_FAN:
00396         for(int i = 1; i < cnt; i += 2) {
00397             gl_draw_triangle(c, &c->vertex[0], &c->vertex[i], &c->vertex[i + 1]);
00398         }
00399         break;
00400     case TGL_QUADS:
00401         for(int i = 0; i < cnt; i += 4) {
00402             c->vertex[i + 2].edge_flag = 0;
00403             gl_draw_triangle(c, &c->vertex[i], &c->vertex[i + 1], &c->vertex[i + 2]);
00404             c->vertex[i + 2].edge_flag = 1;
00405             c->vertex[i + 0].edge_flag = 0;
00406             gl_draw_triangle(c, &c->vertex[i], &c->vertex[i + 2], &c->vertex[i + 3]);
00407         }
00408         break;
00409     case TGL_QUAD_STRIP:
00410         for( ; n >= 4; n -= 2) {
00411             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
00412             gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]);
00413             for (int i = 0; i < 2; i++) {
00414                 c->vertex[i] = c->vertex[i + 2];
00415             }
00416         }
00417         break;
00418     case TGL_POLYGON: {
00419         for (int i = c->vertex_cnt; i >= 3; i--) {
00420             gl_draw_triangle(c, &c->vertex[i - 1], &c->vertex[0], &c->vertex[i - 2]);
00421         }
00422         break;
00423     }
00424     default:
00425         error("glBegin: type %x not handled", c->begin_type);
00426     }
00427 
00428     c->vertex = prevVertex;
00429     c->vertex_cnt = prevVertexCount;
00430 
00431     if (restoreState) {
00432         applyState(backupState);
00433     }
00434 }
00435 
00436 RasterizationDrawCall::RasterizationState RasterizationDrawCall::captureState() const {
00437     RasterizationState state;
00438     TinyGL::GLContext *c = TinyGL::gl_get_context();
00439     state.alphaTest = c->fb->isAlphaTestEnabled();
00440     c->fb->getBlendingFactors(state.sfactor, state.dfactor);
00441     state.enableBlending = c->fb->isBlendingEnabled();
00442     state.alphaFunc = c->fb->getAlphaTestFunc();
00443     state.alphaRefValue = c->fb->getAlphaTestRefVal();
00444 
00445     state.cullFaceEnabled = c->cull_face_enabled;
00446     state.beginType = c->begin_type;
00447     state.colorMask = c->color_mask;
00448     state.currentFrontFace = c->current_front_face;
00449     state.currentShadeModel = c->current_shade_model;
00450     state.depthTest = c->depth_test;
00451     state.polygonModeBack = c->polygon_mode_back;
00452     state.polygonModeFront = c->polygon_mode_front;
00453     state.shadowMode = c->shadow_mode;
00454     state.texture2DEnabled = c->texture_2d_enabled;
00455     state.texture = c->current_texture;
00456     state.shadowMaskBuf = c->fb->shadow_mask_buf;
00457     state.depthFunction = c->fb->getDepthFunc();
00458     state.depthWrite = c->fb->getDepthWrite();
00459     state.lightingEnabled = c->lighting_enabled;
00460     state.depthTestEnabled = c->fb->getDepthTestEnabled();
00461     if (c->current_texture != nullptr) 
00462         state.textureVersion = c->current_texture->versionNumber;
00463 
00464     memcpy(state.viewportScaling, c->viewport.scale._v, sizeof(c->viewport.scale._v));
00465     memcpy(state.viewportTranslation, c->viewport.trans._v, sizeof(c->viewport.trans._v));
00466 
00467     return state;
00468 }
00469 
00470 void RasterizationDrawCall::applyState(const RasterizationDrawCall::RasterizationState &state) const {
00471     TinyGL::GLContext *c = TinyGL::gl_get_context();
00472     c->fb->setBlendingFactors(state.sfactor, state.dfactor);
00473     c->fb->enableBlending(state.enableBlending);
00474     c->fb->enableAlphaTest(state.alphaTest);
00475     c->fb->setAlphaTestFunc(state.alphaFunc, state.alphaRefValue);
00476     c->fb->setDepthFunc(state.depthFunction);
00477     c->fb->enableDepthWrite(state.depthWrite);
00478     c->fb->enableDepthTest(state.depthTestEnabled);
00479 
00480     c->lighting_enabled = state.lightingEnabled;
00481     c->cull_face_enabled = state.cullFaceEnabled;
00482     c->begin_type = state.beginType;
00483     c->color_mask = state.colorMask;
00484     c->current_front_face = state.currentFrontFace;
00485     c->current_shade_model = state.currentShadeModel;
00486     c->depth_test = state.depthTest;
00487     c->polygon_mode_back = state.polygonModeBack;
00488     c->polygon_mode_front = state.polygonModeFront;
00489     c->shadow_mode = state.shadowMode;
00490     c->texture_2d_enabled = state.texture2DEnabled;
00491     c->current_texture = state.texture; 
00492     c->fb->shadow_mask_buf = state.shadowMaskBuf;
00493 
00494     memcpy(c->viewport.scale._v, state.viewportScaling, sizeof(c->viewport.scale._v));
00495     memcpy(c->viewport.trans._v, state.viewportTranslation, sizeof(c->viewport.trans._v));
00496 }
00497 
00498 void RasterizationDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
00499     TinyGL::GLContext *c = TinyGL::gl_get_context();
00500     c->fb->setScissorRectangle(clippingRectangle);
00501     execute(restoreState);
00502     c->fb->resetScissorRectangle();
00503 }
00504 
00505 bool RasterizationDrawCall::operator==(const RasterizationDrawCall &other) const {
00506     if (_vertexCount == other._vertexCount && 
00507         _drawTriangleFront == other._drawTriangleFront && 
00508         _drawTriangleBack == other._drawTriangleBack && 
00509         _state == other._state) {
00510         for (int i = 0; i < _vertexCount; i++) {
00511             if ((_vertex[i] != other._vertex[i])) {
00512                 return false;
00513             }
00514         }
00515         return true;
00516     }
00517     return false;
00518 }
00519 
00520 BlittingDrawCall::BlittingDrawCall(Graphics::BlitImage *image, const BlitTransform &transform, BlittingMode blittingMode) : DrawCall(DrawCall_Blitting), _transform(transform), _mode(blittingMode), _image(image) {
00521     tglIncBlitImageRef(image);
00522     _blitState = captureState();
00523     _imageVersion = tglGetBlitImageVersion(image);
00524     if (TinyGL::gl_get_context()->_enableDirtyRectangles) {
00525         computeDirtyRegion();
00526     }
00527 }
00528 
00529 BlittingDrawCall::~BlittingDrawCall() {
00530     tglDeleteBlitImage(_image);
00531 }
00532 
00533 void BlittingDrawCall::execute(bool restoreState) const {
00534     BlittingState backupState;
00535     if (restoreState) {
00536         backupState = captureState();
00537     }
00538     applyState(_blitState);
00539 
00540     switch (_mode) {
00541     case Graphics::BlittingDrawCall::BlitMode_Regular:
00542         Graphics::Internal::tglBlit(_image, _transform);
00543         break;
00544     case Graphics::BlittingDrawCall::BlitMode_NoBlend:
00545         Graphics::Internal::tglBlitNoBlend(_image, _transform);
00546         break;
00547     case Graphics::BlittingDrawCall::BlitMode_Fast:
00548         Graphics::Internal::tglBlitFast(_image, _transform._destinationRectangle.left, _transform._destinationRectangle.top);
00549         break;
00550     case Graphics::BlittingDrawCall::BlitMode_ZBuffer:
00551         Graphics::Internal::tglBlitZBuffer(_image, _transform._destinationRectangle.left, _transform._destinationRectangle.top);
00552         break;
00553     default:
00554         break;
00555     }
00556     if (restoreState) {
00557         applyState(backupState);
00558     }
00559 }
00560 
00561 void BlittingDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
00562     Graphics::Internal::tglBlitSetScissorRect(clippingRectangle);
00563     execute(restoreState);
00564     Graphics::Internal::tglBlitResetScissorRect();
00565 }
00566 
00567 BlittingDrawCall::BlittingState BlittingDrawCall::captureState() const {
00568     BlittingState state;
00569     TinyGL::GLContext *c = TinyGL::gl_get_context();
00570     state.alphaTest = c->fb->isAlphaTestEnabled();
00571     c->fb->getBlendingFactors(state.sfactor, state.dfactor);
00572     state.enableBlending = c->fb->isBlendingEnabled();
00573     state.alphaFunc = c->fb->getAlphaTestFunc();
00574     state.alphaRefValue = c->fb->getAlphaTestRefVal();
00575     state.depthTestEnabled = c->fb->getDepthTestEnabled();
00576     return state;
00577 }
00578 
00579 void BlittingDrawCall::applyState(const BlittingState &state) const {
00580     TinyGL::GLContext *c = TinyGL::gl_get_context();
00581     c->fb->setBlendingFactors(state.sfactor, state.dfactor);
00582     c->fb->enableBlending(state.enableBlending);
00583     c->fb->enableAlphaTest(state.alphaTest);
00584     c->fb->setAlphaTestFunc(state.alphaFunc, state.alphaRefValue);
00585     c->fb->enableDepthTest(state.depthTestEnabled);
00586 }
00587 
00588 void BlittingDrawCall::computeDirtyRegion() {
00589     int blitWidth = _transform._destinationRectangle.width();
00590     int blitHeight = _transform._destinationRectangle.height();
00591     if (blitWidth == 0) {
00592         if (_transform._sourceRectangle.width() != 0) {
00593             blitWidth = _transform._sourceRectangle.width();
00594         } else {
00595             tglGetBlitImageSize(_image, blitWidth, blitHeight);
00596         }
00597     } 
00598     if (blitHeight == 0) {
00599         if (_transform._sourceRectangle.height() != 0) {
00600             blitHeight = _transform._sourceRectangle.height();
00601         } else {
00602             tglGetBlitImageSize(_image, blitWidth, blitHeight);
00603         }
00604     }
00605     if (blitWidth == 0 || blitHeight == 0) {
00606         _dirtyRegion = Common::Rect();
00607     } else {
00608         _dirtyRegion = Common::Rect(
00609             _transform._destinationRectangle.left,
00610             _transform._destinationRectangle.top,
00611             _transform._destinationRectangle.left + blitWidth + 1,
00612             _transform._destinationRectangle.top + blitHeight + 1
00613         );
00614         _dirtyRegion.clip(TinyGL::gl_get_context()->renderRect);
00615     }
00616 }
00617 
00618 bool BlittingDrawCall::operator==(const BlittingDrawCall &other) const {
00619     return  _mode == other._mode &&
00620             _image == other._image &&
00621             _transform == other._transform &&
00622             _blitState == other._blitState &&
00623             _imageVersion == tglGetBlitImageVersion(other._image);
00624 }
00625 
00626 ClearBufferDrawCall::ClearBufferDrawCall(bool clearZBuffer, int zValue, bool clearColorBuffer, int rValue, int gValue, int bValue) 
00627     : _clearZBuffer(clearZBuffer), _clearColorBuffer(clearColorBuffer), _zValue(zValue), _rValue(rValue), _gValue(gValue), _bValue(bValue), DrawCall(DrawCall_Clear) {
00628     TinyGL::GLContext *c = TinyGL::gl_get_context();
00629     if (c->_enableDirtyRectangles) {
00630         _dirtyRegion = c->renderRect;
00631     }
00632 }
00633 
00634 void ClearBufferDrawCall::execute(bool restoreState) const {
00635     TinyGL::GLContext *c = TinyGL::gl_get_context();
00636     c->fb->clear(_clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue);
00637 }
00638 
00639 void ClearBufferDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
00640     TinyGL::GLContext *c = TinyGL::gl_get_context();
00641     Common::Rect clearRect = clippingRectangle.findIntersectingRect(getDirtyRegion());
00642     c->fb->clearRegion(clearRect.left, clearRect.top, clearRect.width(), clearRect.height(), _clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue);
00643 }
00644 
00645 bool ClearBufferDrawCall::operator==(const ClearBufferDrawCall &other) const {
00646     return  _clearZBuffer == other._clearZBuffer &&
00647             _clearColorBuffer == other._clearColorBuffer &&
00648             _rValue == other._rValue &&
00649             _gValue == other._gValue &&
00650             _bValue == other._bValue &&
00651             _zValue == other._zValue;
00652 }
00653 
00654 
00655 bool RasterizationDrawCall::RasterizationState::operator==(const RasterizationState &other) const {
00656     return  beginType == other.beginType && 
00657             currentFrontFace == other.currentFrontFace && 
00658             cullFaceEnabled == other.cullFaceEnabled &&
00659             colorMask == other.colorMask &&
00660             depthTest == other.depthTest &&
00661             depthFunction == other.depthFunction &&
00662             depthWrite == other.depthWrite &&
00663             shadowMode == other.shadowMode &&
00664             texture2DEnabled == other.texture2DEnabled &&
00665             currentShadeModel == other.currentShadeModel &&
00666             polygonModeBack == other.polygonModeBack &&
00667             polygonModeFront == other.polygonModeFront &&
00668             lightingEnabled == other.lightingEnabled &&
00669             enableBlending == other.enableBlending &&
00670             sfactor == other.sfactor &&
00671             dfactor == other.dfactor &&
00672             alphaTest == other.alphaTest &&
00673             alphaFunc == other.alphaFunc &&
00674             alphaRefValue == other.alphaRefValue &&
00675             texture == other.texture &&
00676             shadowMaskBuf == other.shadowMaskBuf &&
00677             viewportTranslation[0] == other.viewportTranslation[0] &&
00678             viewportTranslation[1] == other.viewportTranslation[1] &&
00679             viewportTranslation[2] == other.viewportTranslation[2] &&
00680             viewportScaling[0] == other.viewportScaling[0] &&
00681             viewportScaling[1] == other.viewportScaling[1] &&
00682             viewportScaling[2] == other.viewportScaling[2] &&
00683             depthTestEnabled == other.depthTestEnabled &&
00684             textureVersion == texture->versionNumber;
00685 }
00686 
00687 } // end of namespace Graphics
00688 
00689 
00690 void *Internal::allocateFrame(int size) {
00691     TinyGL::GLContext *c = TinyGL::gl_get_context();
00692     return c->_drawCallAllocator[c->_currentAllocatorIndex].allocate(size);
00693 }


Generated on Sat May 18 2019 05:01:30 for ResidualVM by doxygen 1.7.1
curved edge   curved edge