2014-08-15 22:51:49 +02:00
|
|
|
/* ResidualVM - A 3D game interpreter
|
|
|
|
*
|
|
|
|
* ResidualVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the AUTHORS
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
|
|
|
|
* which is licensed under the zlib-license (see LICENSE).
|
|
|
|
* It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
|
|
|
|
*/
|
|
|
|
|
2014-08-07 17:54:53 +02:00
|
|
|
#include "graphics/tinygl/zdirtyrect.h"
|
2014-07-23 21:40:15 +02:00
|
|
|
#include "graphics/tinygl/zgl.h"
|
2014-07-24 19:48:54 +02:00
|
|
|
#include "graphics/tinygl/gl.h"
|
2014-08-05 20:33:42 +02:00
|
|
|
#include "common/debug.h"
|
2014-08-09 14:14:25 +02:00
|
|
|
#include "common/math.h"
|
2014-07-22 14:31:30 +02:00
|
|
|
|
2014-07-25 15:37:42 +02:00
|
|
|
namespace TinyGL {
|
|
|
|
|
2014-08-07 17:38:11 +02:00
|
|
|
void tglIssueDrawCall(Graphics::DrawCall *drawCall) {
|
2014-07-26 17:56:44 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
c->_drawCallsQueue.push_back(drawCall);
|
2014-07-25 15:37:42 +02:00
|
|
|
}
|
|
|
|
|
2014-07-28 18:33:04 +02:00
|
|
|
void tglDrawRectangle(Common::Rect rect, int r, int g, int b) {
|
2014-07-27 19:50:24 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
|
|
|
|
if (rect.left < 0)
|
|
|
|
rect.left = 0;
|
2014-08-13 21:20:15 +02:00
|
|
|
if (rect.right >= c->fb->xsize)
|
2014-07-27 19:50:24 +02:00
|
|
|
rect.right = c->fb->xsize - 1;
|
|
|
|
if (rect.top < 0)
|
|
|
|
rect.top = 0;
|
|
|
|
if (rect.bottom >= c->fb->ysize)
|
|
|
|
rect.bottom = c->fb->ysize - 1;
|
|
|
|
|
|
|
|
for(int x = rect.left; x < rect.right; x++) {
|
2014-07-28 18:33:04 +02:00
|
|
|
c->fb->writePixel(rect.top * c->fb->xsize + x, 255, r, g, b);
|
|
|
|
c->fb->writePixel(rect.bottom * c->fb->xsize + x, 255, r, g, b);
|
2014-07-27 19:50:24 +02:00
|
|
|
}
|
|
|
|
for(int y = rect.top; y < rect.bottom; y++) {
|
2014-07-28 18:33:04 +02:00
|
|
|
c->fb->writePixel(y * c->fb->xsize + rect.left, 255, r, g, b);
|
|
|
|
c->fb->writePixel(y * c->fb->xsize + rect.right, 255, r, g, b);
|
2014-07-27 19:50:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-28 18:33:04 +02:00
|
|
|
struct DirtyRectangle {
|
|
|
|
Common::Rect rectangle;
|
|
|
|
int r, g, b;
|
|
|
|
|
|
|
|
DirtyRectangle() { }
|
2014-08-07 17:31:26 +02:00
|
|
|
DirtyRectangle(Common::Rect rect, int red, int green, int blue) {
|
2014-07-28 18:33:04 +02:00
|
|
|
this->rectangle = rect;
|
2014-08-07 17:31:26 +02:00
|
|
|
this->r = red;
|
|
|
|
this->g = green;
|
|
|
|
this->b = blue;
|
2014-07-28 18:33:04 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-07-26 17:56:44 +02:00
|
|
|
|
2014-08-15 23:53:57 +02:00
|
|
|
void tglDisposeResources(TinyGL::GLContext *c) {
|
|
|
|
// Dispose textures and resources.
|
|
|
|
bool allDisposed = true;
|
|
|
|
do {
|
|
|
|
allDisposed = true;
|
2016-07-17 13:28:22 +00:00
|
|
|
for (int i = 0; i < TEXTURE_HASH_TABLE_SIZE; i++) {
|
|
|
|
TinyGL::GLTexture *t = c->shared_state.texture_hash_table[i];
|
|
|
|
while (t) {
|
|
|
|
if (t->disposed) {
|
2016-07-18 04:34:09 +02:00
|
|
|
TinyGL::free_texture(c, t);
|
2016-07-17 13:28:22 +00:00
|
|
|
allDisposed = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
t = t->next;
|
2014-08-15 23:53:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (allDisposed == false);
|
|
|
|
|
|
|
|
Graphics::Internal::tglCleanupImages();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tglPresentBufferDirtyRects(TinyGL::GLContext *c) {
|
2014-08-09 13:43:47 +02:00
|
|
|
typedef Common::List<Graphics::DrawCall *>::const_iterator DrawCallIterator;
|
|
|
|
typedef Common::List<TinyGL::DirtyRectangle>::iterator RectangleIterator;
|
|
|
|
|
2014-07-28 18:33:04 +02:00
|
|
|
Common::List<DirtyRectangle> rectangles;
|
2014-07-27 19:53:42 +02:00
|
|
|
|
2014-08-09 13:43:47 +02:00
|
|
|
DrawCallIterator itFrame = c->_drawCallsQueue.begin();
|
|
|
|
DrawCallIterator endPrevFrame = c->_previousFrameDrawCallsQueue.end();
|
2014-07-31 15:32:33 +02:00
|
|
|
|
|
|
|
// Compare draw calls.
|
2014-08-09 13:43:47 +02:00
|
|
|
if (c->_drawCallsQueue.size() > 0) {
|
|
|
|
for (DrawCallIterator itPrevFrame = c->_previousFrameDrawCallsQueue.begin();
|
2014-08-15 23:53:57 +02:00
|
|
|
itPrevFrame != endPrevFrame;
|
|
|
|
++itPrevFrame, ++itFrame) {
|
|
|
|
const Graphics::DrawCall ¤tCall = **itFrame;
|
|
|
|
const Graphics::DrawCall &previousCall = **itPrevFrame;
|
|
|
|
|
|
|
|
if (previousCall != currentCall) {
|
|
|
|
while (itPrevFrame != endPrevFrame) {
|
|
|
|
Graphics::DrawCall *dirtyDrawCall = *itPrevFrame;
|
|
|
|
rectangles.push_back(DirtyRectangle(dirtyDrawCall->getDirtyRegion(), 255, 255, 255));
|
|
|
|
++itPrevFrame;
|
|
|
|
}
|
|
|
|
break;
|
2014-08-05 20:33:42 +02:00
|
|
|
}
|
|
|
|
}
|
2014-07-31 15:32:33 +02:00
|
|
|
}
|
|
|
|
|
2014-08-09 13:43:47 +02:00
|
|
|
for ( ; itFrame != c->_drawCallsQueue.end(); ++itFrame) {
|
2014-08-01 19:38:50 +02:00
|
|
|
const Graphics::DrawCall ¤tCall = **itFrame;
|
|
|
|
rectangles.push_back(DirtyRectangle(currentCall.getDirtyRegion(), 255, 0, 0));
|
|
|
|
}
|
2014-07-31 15:32:33 +02:00
|
|
|
|
2014-08-09 14:40:18 +02:00
|
|
|
// This loop increases outer rectangle coordinates to favor merging of adjacent rectangles.
|
2014-08-09 13:43:47 +02:00
|
|
|
for (RectangleIterator it = rectangles.begin(); it != rectangles.end(); ++it) {
|
|
|
|
(*it).rectangle.right++;
|
2014-08-09 14:40:08 +02:00
|
|
|
(*it).rectangle.bottom++;
|
2014-08-05 20:33:42 +02:00
|
|
|
}
|
|
|
|
|
2014-08-01 19:38:50 +02:00
|
|
|
// Merge coalesce dirty rects.
|
2014-07-31 15:32:33 +02:00
|
|
|
bool restartMerge;
|
|
|
|
do {
|
|
|
|
restartMerge = false;
|
2014-08-09 13:43:47 +02:00
|
|
|
for (RectangleIterator it1 = rectangles.begin(); it1 != rectangles.end(); ++it1) {
|
|
|
|
for (RectangleIterator it2 = rectangles.begin(); it2 != rectangles.end();) {
|
2014-08-05 20:33:42 +02:00
|
|
|
if (it1 != it2) {
|
|
|
|
if ((*it1).rectangle.intersects((*it2).rectangle)) {
|
|
|
|
(*it1).rectangle.extend((*it2).rectangle);
|
|
|
|
it2 = rectangles.erase(it2);
|
|
|
|
restartMerge = true;
|
|
|
|
} else {
|
|
|
|
++it2;
|
|
|
|
}
|
2014-08-01 19:38:50 +02:00
|
|
|
} else {
|
|
|
|
++it2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while(restartMerge);
|
2014-07-31 15:32:33 +02:00
|
|
|
|
2014-08-13 21:20:15 +02:00
|
|
|
Common::Rect renderRect(0, 0, c->fb->xsize - 1, c->fb->ysize - 1);
|
|
|
|
|
2014-08-09 13:43:47 +02:00
|
|
|
for (RectangleIterator it1 = rectangles.begin(); it1 != rectangles.end(); ++it1) {
|
|
|
|
RectangleIterator it2 = it1;
|
|
|
|
it2++;
|
2014-08-05 20:33:42 +02:00
|
|
|
while (it2 != rectangles.end()) {
|
2014-08-02 21:50:56 +02:00
|
|
|
if ((*it1).rectangle.contains((*it2).rectangle)) {
|
|
|
|
it2 = rectangles.erase(it2);
|
|
|
|
} else {
|
|
|
|
++it2;
|
2014-07-31 15:32:33 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-13 21:20:15 +02:00
|
|
|
(*it1).rectangle.clip(renderRect);
|
2014-08-01 19:38:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Execute draw calls.
|
2014-08-09 13:43:47 +02:00
|
|
|
for (DrawCallIterator it = c->_drawCallsQueue.begin(); it != c->_drawCallsQueue.end(); ++it) {
|
2014-08-02 21:50:31 +02:00
|
|
|
Common::Rect drawCallRegion = (*it)->getDirtyRegion();
|
2014-08-09 13:43:47 +02:00
|
|
|
for (RectangleIterator itRect = rectangles.begin(); itRect != rectangles.end(); ++itRect) {
|
|
|
|
Common::Rect dirtyRegion = (*itRect).rectangle;
|
2014-08-02 21:50:31 +02:00
|
|
|
if (dirtyRegion.intersects(drawCallRegion) || drawCallRegion.contains(dirtyRegion)) {
|
2014-08-05 20:33:42 +02:00
|
|
|
(*it)->execute(dirtyRegion, true);
|
2014-08-02 21:50:31 +02:00
|
|
|
}
|
2014-08-01 19:38:50 +02:00
|
|
|
}
|
2014-07-31 15:32:33 +02:00
|
|
|
}
|
|
|
|
|
2014-08-01 19:38:50 +02:00
|
|
|
// Dispose not necessary draw calls.
|
2014-08-09 13:43:47 +02:00
|
|
|
for (DrawCallIterator it = c->_previousFrameDrawCallsQueue.begin(); it != c->_previousFrameDrawCallsQueue.end(); ++it) {
|
2014-07-31 15:32:33 +02:00
|
|
|
delete *it;
|
2014-07-23 21:40:15 +02:00
|
|
|
}
|
2014-07-26 17:56:44 +02:00
|
|
|
|
2014-07-31 15:32:33 +02:00
|
|
|
c->_previousFrameDrawCallsQueue = c->_drawCallsQueue;
|
2014-07-25 15:25:03 +02:00
|
|
|
c->_drawCallsQueue.clear();
|
2014-07-23 21:40:15 +02:00
|
|
|
|
2014-08-10 19:38:46 +02:00
|
|
|
#if TGL_DIRTY_RECT_SHOW
|
2014-07-31 15:32:33 +02:00
|
|
|
// Draw debug rectangles.
|
|
|
|
// Note: white rectangles are rectangle that contained other rectangles
|
|
|
|
// blue rectangles are rectangle merged from other rectangles
|
|
|
|
// red rectangles are original dirty rects
|
2014-07-27 19:53:42 +02:00
|
|
|
|
|
|
|
bool blendingEnabled = c->fb->isBlendingEnabled();
|
2016-07-21 05:00:46 +02:00
|
|
|
bool alphaTestEnabled = c->fb->isAlphaTestEnabled();
|
2014-07-27 19:53:42 +02:00
|
|
|
c->fb->enableBlending(false);
|
|
|
|
c->fb->enableAlphaTest(false);
|
|
|
|
|
2014-08-09 13:43:47 +02:00
|
|
|
for (RectangleIterator it = rectangles.begin(); it != rectangles.end(); ++it) {
|
|
|
|
tglDrawRectangle((*it).rectangle, (*it).r, (*it).g, (*it).b);
|
2014-07-25 12:59:51 +02:00
|
|
|
}
|
|
|
|
|
2014-07-27 19:53:42 +02:00
|
|
|
c->fb->enableBlending(blendingEnabled);
|
|
|
|
c->fb->enableAlphaTest(alphaTestEnabled);
|
2014-08-10 19:38:46 +02:00
|
|
|
#endif
|
2014-07-27 19:53:42 +02:00
|
|
|
|
2014-08-15 23:53:57 +02:00
|
|
|
tglDisposeResources(c);
|
2014-08-06 21:52:02 +02:00
|
|
|
|
|
|
|
c->_currentAllocatorIndex++;
|
|
|
|
if (c->_currentAllocatorIndex == 2) {
|
|
|
|
c->_currentAllocatorIndex = 0;
|
|
|
|
c->_drawCallAllocator[0].reset();
|
|
|
|
c->_drawCallAllocator[1].reset();
|
|
|
|
}
|
2014-07-23 14:20:59 +02:00
|
|
|
}
|
2014-07-22 14:31:30 +02:00
|
|
|
|
2014-08-15 23:53:57 +02:00
|
|
|
void tglPresentBufferSimple(TinyGL::GLContext *c) {
|
|
|
|
typedef Common::List<Graphics::DrawCall *>::const_iterator DrawCallIterator;
|
|
|
|
|
|
|
|
for (DrawCallIterator it = c->_drawCallsQueue.begin(); it != c->_drawCallsQueue.end(); ++it) {
|
|
|
|
(*it)->execute(true);
|
|
|
|
delete *it;
|
|
|
|
}
|
|
|
|
|
|
|
|
c->_drawCallsQueue.clear();
|
|
|
|
|
|
|
|
tglDisposeResources(c);
|
|
|
|
|
|
|
|
c->_drawCallAllocator[c->_currentAllocatorIndex].reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tglPresentBuffer() {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
if (c->_enableDirtyRectangles) {
|
|
|
|
tglPresentBufferDirtyRects(c);
|
|
|
|
} else {
|
|
|
|
tglPresentBufferSimple(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-09 12:10:26 +02:00
|
|
|
} // end of namespace TinyGL
|
|
|
|
|
2014-07-23 14:20:59 +02:00
|
|
|
namespace Graphics {
|
2014-07-22 14:31:30 +02:00
|
|
|
|
2014-07-31 15:26:03 +02:00
|
|
|
bool DrawCall::operator==(const DrawCall &other) const {
|
|
|
|
if (_type == other._type) {
|
|
|
|
switch (_type) {
|
2014-08-10 19:37:26 +02:00
|
|
|
case DrawCall_Rasterization:
|
2014-08-16 15:12:19 +02:00
|
|
|
return *(const RasterizationDrawCall *)this == (const RasterizationDrawCall &)other;
|
2014-07-31 15:26:03 +02:00
|
|
|
break;
|
2014-08-10 19:37:26 +02:00
|
|
|
case DrawCall_Blitting:
|
2014-08-16 15:12:19 +02:00
|
|
|
return *(const BlittingDrawCall *)this == (const BlittingDrawCall &)other;
|
2014-07-31 15:26:03 +02:00
|
|
|
break;
|
2014-08-10 19:37:26 +02:00
|
|
|
case DrawCall_Clear:
|
2014-08-16 15:12:19 +02:00
|
|
|
return *(const ClearBufferDrawCall *)this == (const ClearBufferDrawCall &)other;
|
2014-07-31 15:26:03 +02:00
|
|
|
break;
|
|
|
|
default:
|
2014-08-06 01:42:06 +02:00
|
|
|
return false;
|
2014-07-31 15:26:03 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-23 21:40:15 +02:00
|
|
|
RasterizationDrawCall::RasterizationDrawCall() : DrawCall(DrawCall_Rasterization) {
|
2014-07-24 19:48:54 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
_vertexCount = c->vertex_cnt;
|
2014-08-06 21:52:02 +02:00
|
|
|
_vertex = (TinyGL::GLVertex *) ::Internal::allocateFrame(_vertexCount * sizeof(TinyGL::GLVertex));
|
2014-07-24 19:48:54 +02:00
|
|
|
_drawTriangleFront = c->draw_triangle_front;
|
|
|
|
_drawTriangleBack = c->draw_triangle_back;
|
|
|
|
memcpy(_vertex, c->vertex, sizeof(TinyGL::GLVertex) * _vertexCount);
|
2014-08-10 19:39:21 +02:00
|
|
|
_state = captureState();
|
2016-07-21 05:04:19 +02:00
|
|
|
if (c->_enableDirtyRectangles) {
|
|
|
|
computeDirtyRegion();
|
|
|
|
}
|
2014-07-28 18:32:28 +02:00
|
|
|
}
|
|
|
|
|
2014-08-07 17:30:54 +02:00
|
|
|
void RasterizationDrawCall::computeDirtyRegion() {
|
2014-08-05 20:02:23 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
2014-08-09 14:14:25 +02:00
|
|
|
int width = c->fb->xsize;
|
|
|
|
int height = c->fb->ysize;
|
2014-08-06 21:10:04 +02:00
|
|
|
|
2014-08-09 14:14:25 +02:00
|
|
|
int left = width, right = 0, top = height, bottom = 0;
|
|
|
|
|
2014-08-06 21:10:04 +02:00
|
|
|
bool pointInsideVolume = false;
|
2014-07-28 18:32:28 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < _vertexCount; i++) {
|
2014-08-05 20:02:23 +02:00
|
|
|
TinyGL::GLVertex *v = &_vertex[i];
|
2014-08-06 01:42:06 +02:00
|
|
|
float winv;
|
|
|
|
// coordinates
|
|
|
|
winv = (float)(1.0 / v->pc.W);
|
2014-08-06 21:10:04 +02:00
|
|
|
float pcX = v->pc.X * winv;
|
|
|
|
float pcY = v->pc.Y * winv;
|
|
|
|
int screenCoordsX = (int)(pcX * c->viewport.scale.X + c->viewport.trans.X);
|
|
|
|
int screenCoordsY = (int)(pcY * c->viewport.scale.Y + c->viewport.trans.Y);
|
|
|
|
|
|
|
|
left = MIN(left, screenCoordsX);
|
|
|
|
right = MAX(right, screenCoordsX);
|
|
|
|
top = MIN(top, screenCoordsY);
|
|
|
|
bottom = MAX(bottom, screenCoordsY);
|
|
|
|
|
|
|
|
if (!pointInsideVolume) {
|
2014-08-09 14:14:25 +02:00
|
|
|
if (pcX >= -2 && pcX <= 2 && pcY >= -2 && pcY <= 2) { // Normalized cube clipping.
|
2014-08-06 21:10:04 +02:00
|
|
|
pointInsideVolume = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clipping out of screen cases.
|
|
|
|
// Reason: other "out of screen cases are actually full screen quads"
|
|
|
|
if (pointInsideVolume == false) {
|
|
|
|
left = right = top = bottom = 0;
|
|
|
|
}
|
2014-08-05 20:02:23 +02:00
|
|
|
|
2014-08-09 14:14:25 +02:00
|
|
|
// Those nested ifs cover the case where the triangle is slightly offscreen
|
|
|
|
// but it should still be rendered.
|
|
|
|
|
2014-08-06 21:10:04 +02:00
|
|
|
if (left < 0) {
|
|
|
|
left = 0;
|
|
|
|
if (right < left) {
|
|
|
|
left = 0;
|
|
|
|
right = width - 1;
|
2014-07-28 18:32:28 +02:00
|
|
|
}
|
2014-08-06 21:10:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (right >= width) {
|
|
|
|
right = width - 1;
|
|
|
|
if (left > right) {
|
|
|
|
left = 0;
|
|
|
|
right = width - 1;
|
2014-07-28 18:32:28 +02:00
|
|
|
}
|
2014-08-06 21:10:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (top < 0) {
|
|
|
|
top = 0;
|
|
|
|
if (bottom < top) {
|
|
|
|
top = 0;
|
|
|
|
bottom = height - 1;
|
2014-07-28 18:32:28 +02:00
|
|
|
}
|
2014-08-06 21:10:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bottom >= height) {
|
|
|
|
bottom = height - 1;
|
|
|
|
if (top > bottom) {
|
|
|
|
top = 0;
|
|
|
|
bottom = height - 1;
|
2014-07-28 18:32:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 17:30:54 +02:00
|
|
|
_dirtyRegion = Common::Rect(left, top, right, bottom);
|
2014-08-09 14:14:25 +02:00
|
|
|
// This takes into account precision issues that occur during rasterization.
|
|
|
|
_dirtyRegion.left -= 2;
|
|
|
|
_dirtyRegion.top -= 2;
|
|
|
|
_dirtyRegion.right += 2;
|
|
|
|
_dirtyRegion.bottom += 2;
|
2014-07-23 15:14:35 +02:00
|
|
|
}
|
2014-07-22 20:26:42 +02:00
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
void RasterizationDrawCall::execute(bool restoreState) const {
|
2014-07-24 19:48:54 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
RasterizationDrawCall::RasterizationState backupState;
|
|
|
|
if (restoreState) {
|
2014-08-10 19:39:21 +02:00
|
|
|
backupState = captureState();
|
2014-07-27 19:45:33 +02:00
|
|
|
}
|
2014-07-24 19:48:54 +02:00
|
|
|
applyState(_state);
|
|
|
|
|
2014-07-28 18:32:28 +02:00
|
|
|
TinyGL::GLVertex *prevVertex = c->vertex;
|
|
|
|
int prevVertexCount = c->vertex_cnt;
|
|
|
|
|
2014-07-24 19:48:54 +02:00
|
|
|
c->vertex = _vertex;
|
|
|
|
c->vertex_cnt = _vertexCount;
|
|
|
|
c->draw_triangle_front = (TinyGL::gl_draw_triangle_func)_drawTriangleFront;
|
|
|
|
c->draw_triangle_back = (TinyGL::gl_draw_triangle_func)_drawTriangleBack;
|
|
|
|
|
2014-08-10 19:39:21 +02:00
|
|
|
int n = c->vertex_n;
|
|
|
|
int cnt = c->vertex_cnt;
|
2014-07-26 17:55:34 +02:00
|
|
|
|
2014-07-24 19:48:54 +02:00
|
|
|
switch (c->begin_type) {
|
|
|
|
case TGL_POINTS:
|
2014-07-26 17:55:34 +02:00
|
|
|
for(int i = 0; i < cnt; i++) {
|
|
|
|
gl_draw_point(c, &c->vertex[i]);
|
|
|
|
}
|
2014-07-24 19:48:54 +02:00
|
|
|
break;
|
|
|
|
case TGL_LINES:
|
2014-07-26 17:55:34 +02:00
|
|
|
for(int i = 0; i < cnt / 2; i++) {
|
|
|
|
gl_draw_line(c, &c->vertex[i * 2], &c->vertex[i * 2 + 1]);
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGL_LINE_STRIP:
|
|
|
|
case TGL_LINE_LOOP:
|
2016-07-11 14:48:51 +00:00
|
|
|
for(int i = 0; i < cnt - 1; i++) {
|
2014-07-26 17:55:34 +02:00
|
|
|
gl_draw_line(c, &c->vertex[i], &c->vertex[i + 1]);
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
2016-07-11 14:48:51 +00:00
|
|
|
gl_draw_line(c, &c->vertex[cnt - 1], &c->vertex[0]);
|
2014-07-24 19:48:54 +02:00
|
|
|
break;
|
|
|
|
case TGL_TRIANGLES:
|
2016-07-21 01:09:50 +02:00
|
|
|
for(int i = 0; i < cnt; i += 3) {
|
|
|
|
gl_draw_triangle(c, &c->vertex[i], &c->vertex[i + 1], &c->vertex[i + 2]);
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGL_TRIANGLE_STRIP:
|
2014-08-11 17:24:21 +02:00
|
|
|
while (cnt >= 3) {
|
|
|
|
// needed to respect triangle orientation
|
|
|
|
switch (cnt & 1) {
|
|
|
|
case 0:
|
|
|
|
gl_draw_triangle(c, &c->vertex[2], &c->vertex[1], &c->vertex[0]);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cnt--;
|
|
|
|
c->vertex++;
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGL_TRIANGLE_FAN:
|
2014-07-26 17:55:34 +02:00
|
|
|
for(int i = 1; i < cnt; i += 2) {
|
|
|
|
gl_draw_triangle(c, &c->vertex[0], &c->vertex[i], &c->vertex[i + 1]);
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGL_QUADS:
|
2016-07-11 00:30:58 +00:00
|
|
|
for(int i = 0; i < cnt; i += 4) {
|
2014-07-26 17:55:34 +02:00
|
|
|
c->vertex[i + 2].edge_flag = 0;
|
|
|
|
gl_draw_triangle(c, &c->vertex[i], &c->vertex[i + 1], &c->vertex[i + 2]);
|
|
|
|
c->vertex[i + 2].edge_flag = 1;
|
|
|
|
c->vertex[i + 0].edge_flag = 0;
|
|
|
|
gl_draw_triangle(c, &c->vertex[i], &c->vertex[i + 2], &c->vertex[i + 3]);
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGL_QUAD_STRIP:
|
2014-08-09 13:07:46 +02:00
|
|
|
for( ; n >= 4; n -= 2) {
|
2014-07-24 19:48:54 +02:00
|
|
|
gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
|
|
|
|
gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]);
|
2014-08-09 13:07:46 +02:00
|
|
|
for (int i = 0; i < 2; i++) {
|
2014-07-24 19:48:54 +02:00
|
|
|
c->vertex[i] = c->vertex[i + 2];
|
2014-08-09 13:07:46 +02:00
|
|
|
}
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TGL_POLYGON: {
|
2014-08-09 13:07:46 +02:00
|
|
|
for (int i = c->vertex_cnt; i >= 3; i--) {
|
|
|
|
gl_draw_triangle(c, &c->vertex[i - 1], &c->vertex[0], &c->vertex[i - 2]);
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
error("glBegin: type %x not handled", c->begin_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
c->vertex = prevVertex;
|
|
|
|
c->vertex_cnt = prevVertexCount;
|
2014-07-28 18:32:28 +02:00
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
if (restoreState) {
|
|
|
|
applyState(backupState);
|
|
|
|
}
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
|
|
|
|
2014-08-10 19:39:21 +02:00
|
|
|
RasterizationDrawCall::RasterizationState RasterizationDrawCall::captureState() const {
|
2014-07-24 19:48:54 +02:00
|
|
|
RasterizationState state;
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
2014-08-10 19:05:32 +02:00
|
|
|
state.alphaTest = c->fb->isAlphaTestEnabled();
|
2014-07-24 19:48:54 +02:00
|
|
|
c->fb->getBlendingFactors(state.sfactor, state.dfactor);
|
|
|
|
state.enableBlending = c->fb->isBlendingEnabled();
|
|
|
|
state.alphaFunc = c->fb->getAlphaTestFunc();
|
|
|
|
state.alphaRefValue = c->fb->getAlphaTestRefVal();
|
|
|
|
|
|
|
|
state.cullFaceEnabled = c->cull_face_enabled;
|
|
|
|
state.beginType = c->begin_type;
|
|
|
|
state.colorMask = c->color_mask;
|
|
|
|
state.currentFrontFace = c->current_front_face;
|
|
|
|
state.currentShadeModel = c->current_shade_model;
|
|
|
|
state.depthTest = c->depth_test;
|
|
|
|
state.polygonModeBack = c->polygon_mode_back;
|
|
|
|
state.polygonModeFront = c->polygon_mode_front;
|
|
|
|
state.shadowMode = c->shadow_mode;
|
|
|
|
state.texture2DEnabled = c->texture_2d_enabled;
|
|
|
|
state.texture = c->current_texture;
|
|
|
|
state.shadowMaskBuf = c->fb->shadow_mask_buf;
|
2014-07-25 15:47:07 +02:00
|
|
|
state.depthFunction = c->fb->getDepthFunc();
|
|
|
|
state.depthWrite = c->fb->getDepthWrite();
|
|
|
|
state.lightingEnabled = c->lighting_enabled;
|
2014-08-13 14:33:54 +02:00
|
|
|
state.depthTestEnabled = c->fb->getDepthTestEnabled();
|
2014-08-02 21:49:14 +02:00
|
|
|
if (c->current_texture != nullptr)
|
|
|
|
state.textureVersion = c->current_texture->versionNumber;
|
2014-07-25 15:47:07 +02:00
|
|
|
|
|
|
|
memcpy(state.viewportScaling, c->viewport.scale._v, sizeof(c->viewport.scale._v));
|
|
|
|
memcpy(state.viewportTranslation, c->viewport.trans._v, sizeof(c->viewport.trans._v));
|
|
|
|
memcpy(state.currentColor, c->longcurrent_color, sizeof(c->longcurrent_color));
|
2014-07-24 19:48:54 +02:00
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RasterizationDrawCall::applyState(const RasterizationDrawCall::RasterizationState &state) const {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
c->fb->setBlendingFactors(state.sfactor, state.dfactor);
|
|
|
|
c->fb->enableBlending(state.enableBlending);
|
|
|
|
c->fb->enableAlphaTest(state.alphaTest);
|
|
|
|
c->fb->setAlphaTestFunc(state.alphaFunc, state.alphaRefValue);
|
2014-07-25 15:47:07 +02:00
|
|
|
c->fb->setDepthFunc(state.depthFunction);
|
|
|
|
c->fb->enableDepthWrite(state.depthWrite);
|
2014-08-13 14:33:54 +02:00
|
|
|
c->fb->enableDepthTest(state.depthTestEnabled);
|
2014-07-24 19:48:54 +02:00
|
|
|
|
2014-07-25 15:47:07 +02:00
|
|
|
c->lighting_enabled = state.lightingEnabled;
|
2014-07-24 19:48:54 +02:00
|
|
|
c->cull_face_enabled = state.cullFaceEnabled;
|
|
|
|
c->begin_type = state.beginType;
|
|
|
|
c->color_mask = state.colorMask;
|
|
|
|
c->current_front_face = state.currentFrontFace;
|
|
|
|
c->current_shade_model = state.currentShadeModel;
|
|
|
|
c->depth_test = state.depthTest;
|
|
|
|
c->polygon_mode_back = state.polygonModeBack;
|
|
|
|
c->polygon_mode_front = state.polygonModeFront;
|
|
|
|
c->shadow_mode = state.shadowMode;
|
|
|
|
c->texture_2d_enabled = state.texture2DEnabled;
|
|
|
|
c->current_texture = state.texture;
|
|
|
|
c->fb->shadow_mask_buf = state.shadowMaskBuf;
|
2014-07-25 15:47:07 +02:00
|
|
|
|
|
|
|
memcpy(c->viewport.scale._v, state.viewportScaling, sizeof(c->viewport.scale._v));
|
|
|
|
memcpy(c->viewport.trans._v, state.viewportTranslation, sizeof(c->viewport.trans._v));
|
|
|
|
memcpy(c->longcurrent_color, state.currentColor, sizeof(c->longcurrent_color));
|
2014-07-24 19:48:54 +02:00
|
|
|
}
|
2014-07-22 20:26:42 +02:00
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
void RasterizationDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
|
2014-08-01 19:36:14 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
c->fb->setScissorRectangle(clippingRectangle.left, clippingRectangle.right, clippingRectangle.top, clippingRectangle.bottom);
|
|
|
|
execute(restoreState);
|
|
|
|
c->fb->setScissorRectangle(0, c->fb->xsize, 0, c->fb->ysize);
|
2014-07-27 19:45:33 +02:00
|
|
|
}
|
2014-07-22 20:26:42 +02:00
|
|
|
|
2014-07-27 19:53:10 +02:00
|
|
|
const Common::Rect RasterizationDrawCall::getDirtyRegion() const {
|
2014-07-28 18:32:28 +02:00
|
|
|
return _dirtyRegion;
|
2014-07-23 15:14:35 +02:00
|
|
|
}
|
2014-07-22 20:26:42 +02:00
|
|
|
|
2014-07-31 15:26:03 +02:00
|
|
|
bool RasterizationDrawCall::operator==(const RasterizationDrawCall &other) const {
|
2014-08-03 21:02:16 +02:00
|
|
|
if (_vertexCount == other._vertexCount &&
|
|
|
|
_drawTriangleFront == other._drawTriangleFront &&
|
|
|
|
_drawTriangleBack == other._drawTriangleBack &&
|
|
|
|
_state == other._state) {
|
2014-07-31 15:26:03 +02:00
|
|
|
for (int i = 0; i < _vertexCount; i++) {
|
2014-08-09 12:34:40 +02:00
|
|
|
if ((_vertex[i] != other._vertex[i])) {
|
2014-07-31 15:26:03 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-23 21:40:15 +02:00
|
|
|
BlittingDrawCall::BlittingDrawCall(Graphics::BlitImage *image, const BlitTransform &transform, BlittingMode blittingMode) : DrawCall(DrawCall_Blitting), _transform(transform), _mode(blittingMode), _image(image) {
|
2014-08-10 19:39:21 +02:00
|
|
|
_blitState = captureState();
|
2014-08-02 21:49:14 +02:00
|
|
|
_imageVersion = tglGetBlitImageVersion(image);
|
2014-07-23 15:14:35 +02:00
|
|
|
}
|
2014-07-23 14:20:59 +02:00
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
void BlittingDrawCall::execute(bool restoreState) const {
|
|
|
|
BlittingState backupState;
|
|
|
|
if (restoreState) {
|
2014-08-10 19:39:21 +02:00
|
|
|
backupState = captureState();
|
2014-07-27 19:45:33 +02:00
|
|
|
}
|
2014-07-23 21:40:15 +02:00
|
|
|
applyState(_blitState);
|
|
|
|
|
2014-07-25 15:45:52 +02:00
|
|
|
switch (_mode) {
|
2014-07-23 21:40:15 +02:00
|
|
|
case Graphics::BlittingDrawCall::BlitMode_Regular:
|
|
|
|
Graphics::Internal::tglBlit(_image, _transform);
|
|
|
|
break;
|
|
|
|
case Graphics::BlittingDrawCall::BlitMode_NoBlend:
|
|
|
|
Graphics::Internal::tglBlitNoBlend(_image, _transform);
|
|
|
|
break;
|
|
|
|
case Graphics::BlittingDrawCall::BlitMode_Fast:
|
|
|
|
Graphics::Internal::tglBlitFast(_image, _transform._destinationRectangle.left, _transform._destinationRectangle.top);
|
|
|
|
break;
|
2014-07-25 15:45:52 +02:00
|
|
|
case Graphics::BlittingDrawCall::BlitMode_ZBuffer:
|
2014-07-27 19:45:33 +02:00
|
|
|
Graphics::Internal::tglBlitZBuffer(_image, _transform._destinationRectangle.left, _transform._destinationRectangle.top);
|
2014-07-25 15:45:52 +02:00
|
|
|
break;
|
2014-07-23 21:40:15 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2014-07-27 19:45:33 +02:00
|
|
|
if (restoreState) {
|
|
|
|
applyState(backupState);
|
|
|
|
}
|
2014-07-23 15:14:35 +02:00
|
|
|
}
|
2014-07-22 20:26:42 +02:00
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
void BlittingDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
|
2014-08-10 19:38:06 +02:00
|
|
|
Graphics::Internal::tglBlitSetScissorRect(clippingRectangle.left, clippingRectangle.top, clippingRectangle.right, clippingRectangle.bottom);
|
2014-08-01 19:36:14 +02:00
|
|
|
execute(restoreState);
|
2014-08-10 19:38:06 +02:00
|
|
|
Graphics::Internal::tglBlitSetScissorRect(0, 0, 0, 0);
|
2014-07-22 14:31:30 +02:00
|
|
|
}
|
2014-07-23 15:14:35 +02:00
|
|
|
|
2014-08-10 19:39:21 +02:00
|
|
|
BlittingDrawCall::BlittingState BlittingDrawCall::captureState() const {
|
2014-07-23 21:40:15 +02:00
|
|
|
BlittingState state;
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
2014-08-10 19:05:32 +02:00
|
|
|
state.alphaTest = c->fb->isAlphaTestEnabled();
|
2014-07-23 21:40:15 +02:00
|
|
|
c->fb->getBlendingFactors(state.sfactor, state.dfactor);
|
|
|
|
state.enableBlending = c->fb->isBlendingEnabled();
|
|
|
|
state.alphaFunc = c->fb->getAlphaTestFunc();
|
|
|
|
state.alphaRefValue = c->fb->getAlphaTestRefVal();
|
2014-08-13 14:33:54 +02:00
|
|
|
state.depthTestEnabled = c->fb->getDepthTestEnabled();
|
2014-07-23 21:40:15 +02:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlittingDrawCall::applyState(const BlittingState &state) const {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
c->fb->setBlendingFactors(state.sfactor, state.dfactor);
|
|
|
|
c->fb->enableBlending(state.enableBlending);
|
|
|
|
c->fb->enableAlphaTest(state.alphaTest);
|
|
|
|
c->fb->setAlphaTestFunc(state.alphaFunc, state.alphaRefValue);
|
2014-08-13 14:33:54 +02:00
|
|
|
c->fb->enableDepthTest(state.depthTestEnabled);
|
2014-07-23 21:40:15 +02:00
|
|
|
}
|
|
|
|
|
2014-07-27 19:53:10 +02:00
|
|
|
const Common::Rect BlittingDrawCall::getDirtyRegion() const {
|
|
|
|
int blitWidth = _transform._destinationRectangle.width();
|
2014-08-01 19:39:06 +02:00
|
|
|
int blitHeight = _transform._destinationRectangle.height();
|
2014-07-27 19:53:10 +02:00
|
|
|
if (blitWidth == 0) {
|
|
|
|
if (_transform._sourceRectangle.width() != 0) {
|
|
|
|
blitWidth = _transform._sourceRectangle.width();
|
|
|
|
} else {
|
|
|
|
tglGetBlitImageSize(_image, blitWidth, blitHeight);
|
|
|
|
}
|
2014-08-03 22:17:02 +02:00
|
|
|
}
|
|
|
|
if (blitHeight == 0) {
|
2014-07-27 19:53:10 +02:00
|
|
|
if (_transform._sourceRectangle.height() != 0) {
|
|
|
|
blitHeight = _transform._sourceRectangle.height();
|
|
|
|
} else {
|
|
|
|
tglGetBlitImageSize(_image, blitWidth, blitHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Common::Rect(_transform._destinationRectangle.left, _transform._destinationRectangle.top, _transform._destinationRectangle.left + blitWidth, _transform._destinationRectangle.top + blitHeight);
|
|
|
|
}
|
|
|
|
|
2014-07-31 15:26:03 +02:00
|
|
|
bool BlittingDrawCall::operator==(const BlittingDrawCall &other) const {
|
2014-08-03 21:04:35 +02:00
|
|
|
return _mode == other._mode &&
|
|
|
|
_image == other._image &&
|
|
|
|
_transform == other._transform &&
|
|
|
|
_blitState == other._blitState &&
|
|
|
|
_imageVersion == tglGetBlitImageVersion(other._image);
|
2014-07-31 15:26:03 +02:00
|
|
|
}
|
|
|
|
|
2014-08-10 19:39:38 +02:00
|
|
|
ClearBufferDrawCall::ClearBufferDrawCall(bool clearZBuffer, int zValue, bool clearColorBuffer, int rValue, int gValue, int bValue)
|
|
|
|
: _clearZBuffer(clearZBuffer), _clearColorBuffer(clearColorBuffer), _zValue(zValue), _rValue(rValue), _gValue(gValue), _bValue(bValue), DrawCall(DrawCall_Clear) {
|
2014-07-25 15:41:32 +02:00
|
|
|
}
|
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
void ClearBufferDrawCall::execute(bool restoreState) const {
|
2014-07-25 15:41:32 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
2014-08-07 17:30:23 +02:00
|
|
|
c->fb->clear(_clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue);
|
2014-07-25 15:41:32 +02:00
|
|
|
}
|
|
|
|
|
2014-07-27 19:45:33 +02:00
|
|
|
void ClearBufferDrawCall::execute(const Common::Rect &clippingRectangle, bool restoreState) const {
|
2014-08-01 19:36:14 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
2014-08-07 17:30:23 +02:00
|
|
|
c->fb->clearRegion(clippingRectangle.left, clippingRectangle.top, clippingRectangle.width(), clippingRectangle.height(), _clearZBuffer, _zValue, _clearColorBuffer, _rValue, _gValue, _bValue);
|
2014-07-25 15:41:32 +02:00
|
|
|
}
|
|
|
|
|
2014-07-27 19:53:10 +02:00
|
|
|
const Common::Rect ClearBufferDrawCall::getDirtyRegion() const {
|
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
return Common::Rect(0, 0, c->fb->xsize, c->fb->ysize);
|
|
|
|
}
|
|
|
|
|
2014-07-31 15:26:03 +02:00
|
|
|
bool ClearBufferDrawCall::operator==(const ClearBufferDrawCall &other) const {
|
2014-08-07 17:30:23 +02:00
|
|
|
return _clearZBuffer == other._clearZBuffer &&
|
|
|
|
_clearColorBuffer == other._clearColorBuffer &&
|
|
|
|
_rValue == other._rValue &&
|
|
|
|
_gValue == other._gValue &&
|
|
|
|
_bValue == other._bValue &&
|
|
|
|
_zValue == other._zValue;
|
2014-07-31 15:26:03 +02:00
|
|
|
}
|
|
|
|
|
2014-08-02 21:49:14 +02:00
|
|
|
|
|
|
|
bool RasterizationDrawCall::RasterizationState::operator==(const RasterizationState &other) const {
|
2014-08-03 21:05:07 +02:00
|
|
|
return beginType == other.beginType &&
|
|
|
|
currentFrontFace == other.currentFrontFace &&
|
|
|
|
cullFaceEnabled == other.cullFaceEnabled &&
|
|
|
|
colorMask == other.colorMask &&
|
|
|
|
depthTest == other.depthTest &&
|
|
|
|
depthFunction == other.depthFunction &&
|
|
|
|
depthWrite == other.depthWrite &&
|
|
|
|
shadowMode == other.shadowMode &&
|
|
|
|
texture2DEnabled == other.texture2DEnabled &&
|
|
|
|
currentShadeModel == other.currentShadeModel &&
|
|
|
|
polygonModeBack == other.polygonModeBack &&
|
|
|
|
polygonModeFront == other.polygonModeFront &&
|
|
|
|
lightingEnabled == other.lightingEnabled &&
|
|
|
|
enableBlending == other.enableBlending &&
|
|
|
|
sfactor == other.sfactor &&
|
|
|
|
dfactor == other.dfactor &&
|
|
|
|
alphaTest == other.alphaTest &&
|
|
|
|
alphaFunc == other.alphaFunc &&
|
|
|
|
alphaRefValue == other.alphaRefValue &&
|
|
|
|
texture == other.texture &&
|
|
|
|
shadowMaskBuf == other.shadowMaskBuf &&
|
|
|
|
currentColor[0] == other.currentColor[0] &&
|
|
|
|
currentColor[1] == other.currentColor[1] &&
|
|
|
|
currentColor[2] == other.currentColor[2] &&
|
|
|
|
currentColor[3] == other.currentColor[3] &&
|
|
|
|
viewportTranslation[0] == other.viewportTranslation[0] &&
|
|
|
|
viewportTranslation[1] == other.viewportTranslation[1] &&
|
|
|
|
viewportTranslation[2] == other.viewportTranslation[2] &&
|
|
|
|
viewportScaling[0] == other.viewportScaling[0] &&
|
|
|
|
viewportScaling[1] == other.viewportScaling[1] &&
|
|
|
|
viewportScaling[2] == other.viewportScaling[2] &&
|
2014-08-13 14:33:54 +02:00
|
|
|
depthTestEnabled == other.depthTestEnabled &&
|
2014-08-03 21:05:07 +02:00
|
|
|
textureVersion == texture->versionNumber;
|
2014-08-02 21:49:14 +02:00
|
|
|
}
|
|
|
|
|
2014-07-23 15:14:35 +02:00
|
|
|
} // end of namespace Graphics
|
2014-08-03 21:05:07 +02:00
|
|
|
|
2014-08-06 21:52:02 +02:00
|
|
|
|
2014-08-07 21:48:38 +02:00
|
|
|
void *Internal::allocateFrame(int size) {
|
2014-08-06 21:52:02 +02:00
|
|
|
TinyGL::GLContext *c = TinyGL::gl_get_context();
|
|
|
|
return c->_drawCallAllocator[c->_currentAllocatorIndex].allocate(size);
|
|
|
|
}
|