Merge revisions r5455:r5474 from trunk to ogl-es

Add color-mask fixes to ogles2 and webgl drivers.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@5475 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2017-06-07 15:20:59 +00:00
parent c3ed02c8d0
commit 56e72da4a7
15 changed files with 176 additions and 209 deletions

View File

@ -10,6 +10,8 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point)
-------------------------- --------------------------
Changes in 1.9 (not yet released) Changes in 1.9 (not yet released)
- Lets the BSP loader find textures inserted with relative paths. Thx@ curaga for patch
- Slightly simplified ALLOC_STRATEGY_DOUBLE in arrays
- Add alternavive BoundingBox calculation for BillboardSceneNode which can take in a camera node. Thx @Seven and @JacKDuRdEn for bugreports. - Add alternavive BoundingBox calculation for BillboardSceneNode which can take in a camera node. Thx @Seven and @JacKDuRdEn for bugreports.
- FPS camera now supports keyboard rotation. - FPS camera now supports keyboard rotation.
- Base FPS-camera movement on last position of mouse instead of always center (works better on platforms where cursor-placement is not allowed) - Base FPS-camera movement on last position of mouse instead of always center (works better on platforms where cursor-placement is not allowed)

View File

@ -220,7 +220,9 @@ void loadModel(const c8* fn)
return; return;
} }
u32 then = Device->getTimer()->getRealTime();
scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() ); scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() );
Device->getLogger()->log("Loading time (ms): ", core::stringc(Device->getTimer()->getRealTime() - then).c_str());
if (!m) if (!m)
{ {
@ -323,7 +325,7 @@ void createToolBox()
} }
/* /*
Function updateToolBox() is called each frame to update dynamic information in Function updateToolBox() is called each frame to update dynamic information in
the toolbox. the toolbox.
*/ */
void updateToolBox() void updateToolBox()
@ -354,8 +356,8 @@ void updateToolBox()
void onKillFocus() void onKillFocus()
{ {
// Avoid that the FPS-camera continues moving when the user presses alt-tab while // Avoid that the FPS-camera continues moving when the user presses alt-tab while
// moving the camera. // moving the camera.
const core::list<scene::ISceneNodeAnimator*>& animators = Camera[1]->getAnimators(); const core::list<scene::ISceneNodeAnimator*>& animators = Camera[1]->getAnimators();
core::list<irr::scene::ISceneNodeAnimator*>::ConstIterator iter = animators.begin(); core::list<irr::scene::ISceneNodeAnimator*>::ConstIterator iter = animators.begin();
while ( iter != animators.end() ) while ( iter != animators.end() )
@ -524,11 +526,11 @@ public:
*/ */
bool OnKeyUp(irr::EKEY_CODE keyCode) bool OnKeyUp(irr::EKEY_CODE keyCode)
{ {
// Don't handle keys if we have a modal dialog open as it would lead // Don't handle keys if we have a modal dialog open as it would lead
// to unexpected application behaviour for the user. // to unexpected application behaviour for the user.
if ( hasModalDialog() ) if ( hasModalDialog() )
return false; return false;
if (keyCode == irr::KEY_ESCAPE) if (keyCode == irr::KEY_ESCAPE)
{ {
if (Device) if (Device)

View File

@ -856,6 +856,10 @@ namespace quake3
loadFile.append ( extension[g] ); loadFile.append ( extension[g] );
} }
texture = driver->findTexture( loadFile );
if ( texture )
break;
if ( fileSystem->existFile ( loadFile ) ) if ( fileSystem->existFile ( loadFile ) )
{ {
texture = driver->getTexture( loadFile ); texture = driver->getTexture( loadFile );

View File

@ -1081,10 +1081,10 @@ namespace scene
//! Get scene nodes by type. //! Get scene nodes by type.
/** \param type: Type of scene node to find (ESNT_ANY will return all child nodes). /** \param type: Type of scene node to find (ESNT_ANY will return all child nodes).
\param outNodes: array to be filled with results. \param outNodes: results will be added to this array (outNodes is not cleared).
\param start: Scene node to start from. All children of this scene \param start: Scene node to start from. This node and all children of this scene
node are searched. If null is specified, the root scene node is node are checked (recursively, so also children of children, etc). If null is specified,
taken. */ the root scene node is taken as start-node. */
virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type,
core::array<scene::ISceneNode*>& outNodes, core::array<scene::ISceneNode*>& outNodes,
ISceneNode* start=0) = 0; ISceneNode* start=0) = 0;

View File

@ -22,12 +22,12 @@ class ITriangleSelector;
class IMeshBuffer; class IMeshBuffer;
//! Additional information about the triangle arrays returned by ITriangleSelector::getTriangles //! Additional information about the triangle arrays returned by ITriangleSelector::getTriangles
/** ITriangleSelector are free to fill out this information fully, partly or ignore it. /** ITriangleSelector are free to fill out this information fully, partly or ignore it.
Usually they will try to fill it when they can and set values to 0 otherwise. Usually they will try to fill it when they can and set values to 0 otherwise.
*/ */
struct SCollisionTriangleRange struct SCollisionTriangleRange
{ {
SCollisionTriangleRange() SCollisionTriangleRange()
: RangeStart(0), RangeSize(0) : RangeStart(0), RangeSize(0)
, Selector(0), SceneNode(0) , Selector(0), SceneNode(0)
, MeshBuffer(0), MaterialIndex(0) , MeshBuffer(0), MaterialIndex(0)
@ -42,10 +42,10 @@ struct SCollisionTriangleRange
return triangleIndex >= RangeStart && triangleIndex < RangeStart+RangeSize; return triangleIndex >= RangeStart && triangleIndex < RangeStart+RangeSize;
} }
//! First index in the array for which this struct is valid //! First index in the returned triangle array for which this struct is valid
irr::u32 RangeStart; irr::u32 RangeStart;
//! Number of elements in the array for which this struct is valid (starting with RangeStart) //! Number of elements in the returned triangle array for which this struct is valid (starting with RangeStart)
irr::u32 RangeSize; irr::u32 RangeSize;
//! Real selector which contained those triangles (useful when working with MetaTriangleSelector) //! Real selector which contained those triangles (useful when working with MetaTriangleSelector)
@ -89,17 +89,17 @@ public:
into the array. into the array.
\param transform Pointer to matrix for transforming the triangles \param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles before they are returned. Useful for example to scale all triangles
down into an ellipsoid space. down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the \param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix. triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that \param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles. array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. has distinguishable information. For example one range per meshbuffer.
*/ */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::matrix4* transform=0, s32& outTriangleCount, const core::matrix4* transform=0,
bool useNodeTransform=true, bool useNodeTransform=true,
irr::core::array<SCollisionTriangleRange>* outTriangleInfo=0) const = 0; irr::core::array<SCollisionTriangleRange>* outTriangleInfo=0) const = 0;
//! Gets the triangles for one associated node which may lie within a specific bounding box. //! Gets the triangles for one associated node which may lie within a specific bounding box.
@ -120,12 +120,12 @@ public:
will be written into the array. will be written into the array.
\param transform Pointer to matrix for transforming the triangles \param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles before they are returned. Useful for example to scale all triangles
down into an ellipsoid space. down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the \param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix. triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that \param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles. array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. */ has distinguishable information. For example one range per meshbuffer. */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::aabbox3d<f32>& box, s32& outTriangleCount, const core::aabbox3d<f32>& box,
@ -150,12 +150,12 @@ public:
will be written into the array. will be written into the array.
\param transform Pointer to matrix for transforming the triangles \param transform Pointer to matrix for transforming the triangles
before they are returned. Useful for example to scale all triangles before they are returned. Useful for example to scale all triangles
down into an ellipsoid space. down into an ellipsoid space.
\param useNodeTransform When the selector has a node then transform the \param useNodeTransform When the selector has a node then transform the
triangles by that node's transformation matrix. triangles by that node's transformation matrix.
\param outTriangleInfo When a pointer to an array is passed then that \param outTriangleInfo When a pointer to an array is passed then that
array is filled with additional information about the returned triangles. array is filled with additional information about the returned triangles.
One element of SCollisionTriangleRange added for each range of triangles which One element of SCollisionTriangleRange added for each range of triangles which
has distinguishable information. For example one range per meshbuffer. */ has distinguishable information. For example one range per meshbuffer. */
virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
s32& outTriangleCount, const core::line3d<f32>& line, s32& outTriangleCount, const core::line3d<f32>& line,
@ -179,7 +179,7 @@ public:
//! Get scene node associated with a given triangle. //! Get scene node associated with a given triangle.
/** With CMetaTriangleSelector-selectors it's possible to find out a node /** With CMetaTriangleSelector-selectors it's possible to find out a node
belonging to a certain triangle index. belonging to a certain triangle index.
NOTE: triangleIndex has nothing to do with the order of triangles returned by getTriangles functions! NOTE: triangleIndex has nothing to do with the order of triangles returned by getTriangles functions!
So you can _not_ use this function to find out anything about to which node returned triangles belong. So you can _not_ use this function to find out anything about to which node returned triangles belong.
Use STriangleCollisionInfo struct for that. Use STriangleCollisionInfo struct for that.

View File

@ -108,12 +108,12 @@ public:
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#endif #endif
//! defines an allocation strategy //! defines an allocation strategy (used only by irr::array so far)
enum eAllocStrategy enum eAllocStrategy
{ {
ALLOC_STRATEGY_SAFE = 0, ALLOC_STRATEGY_SAFE = 0, // increase size by 1
ALLOC_STRATEGY_DOUBLE = 1, ALLOC_STRATEGY_DOUBLE = 1, // double size when under 500 elements, beyond that increase by 1/4th size. Plus a small constant.
ALLOC_STRATEGY_SQRT = 2 ALLOC_STRATEGY_SQRT = 2 // not implemented
}; };

View File

@ -126,9 +126,7 @@ public:
//! Insert item into array at specified position. //! Insert item into array at specified position.
/** Please use this only if you know what you are doing (possible /**
performance loss). The preferred method of adding elements should be
push_back().
\param element: Element to be inserted \param element: Element to be inserted
\param index: Where position to insert the new element. */ \param index: Where position to insert the new element. */
void insert(const T& element, u32 index=0) void insert(const T& element, u32 index=0)
@ -147,8 +145,7 @@ public:
switch ( strategy ) switch ( strategy )
{ {
case ALLOC_STRATEGY_DOUBLE: case ALLOC_STRATEGY_DOUBLE:
newAlloc = used + 1 + (allocated < 500 ? newAlloc = used + 5 + (allocated < 500 ? used : used >> 2);
(allocated < 5 ? 5 : used) : used >> 2);
break; break;
default: default:
case ALLOC_STRATEGY_SAFE: case ALLOC_STRATEGY_SAFE:

View File

@ -243,7 +243,7 @@ namespace core
//! returns if a equals b, taking possible rounding errors into account //! returns if a equals b, taking possible rounding errors into account
template <class T> template <class T>
inline T equals(const T a, const T b, const T tolerance = roundingError<T>()) inline bool equals(const T a, const T b, const T tolerance = roundingError<T>())
{ {
return (a + tolerance >= b) && (a - tolerance <= b); return (a + tolerance >= b) && (a - tolerance <= b);
} }

View File

@ -580,12 +580,14 @@ void CGUITabControl::draw()
core::rect<s32> frameRect(AbsoluteRect); core::rect<s32> frameRect(AbsoluteRect);
// some empty background as placeholder when there are no tabs
if (Tabs.empty()) if (Tabs.empty())
driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
if (!font) if (!font)
return; return;
// tab button bar can be above or below the tabs
if ( VerticalAlignment == EGUIA_UPPERLEFT ) if ( VerticalAlignment == EGUIA_UPPERLEFT )
{ {
frameRect.UpperLeftCorner.Y += 2; frameRect.UpperLeftCorner.Y += 2;
@ -610,6 +612,7 @@ void CGUITabControl::draw()
//const wchar_t* activetext = 0; //const wchar_t* activetext = 0;
CGUITab *activeTab = 0; CGUITab *activeTab = 0;
// Draw all tab-buttons except the active one
for (u32 i=CurrentScrollTabIndex; i<Tabs.size(); ++i) for (u32 i=CurrentScrollTabIndex; i<Tabs.size(); ++i)
{ {
// get Text // get Text
@ -636,6 +639,7 @@ void CGUITabControl::draw()
if ((s32)i == ActiveTab) if ((s32)i == ActiveTab)
{ {
// for active button just remember values
left = frameRect.UpperLeftCorner.X; left = frameRect.UpperLeftCorner.X;
right = frameRect.LowerRightCorner.X; right = frameRect.LowerRightCorner.X;
//activetext = text; //activetext = text;
@ -653,7 +657,8 @@ void CGUITabControl::draw()
} }
} }
// draw active tab // Draw active tab button
// Drawn later than other buttons because it draw over the buttons before/after it.
if (left != 0 && right != 0 && activeTab != 0) if (left != 0 && right != 0 && activeTab != 0)
{ {
// draw upper highlight frame // draw upper highlight frame
@ -683,7 +688,6 @@ void CGUITabControl::draw()
} }
else else
{ {
frameRect.UpperLeftCorner.X = left-2; frameRect.UpperLeftCorner.X = left-2;
frameRect.LowerRightCorner.X = right+2; frameRect.LowerRightCorner.X = right+2;
frameRect.LowerRightCorner.Y += 2; frameRect.LowerRightCorner.Y += 2;
@ -707,24 +711,26 @@ void CGUITabControl::draw()
} }
else else
{ {
// No active tab
// Draw a line separating button bar from tab area
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
if ( VerticalAlignment == EGUIA_UPPERLEFT ) if ( VerticalAlignment == EGUIA_UPPERLEFT )
{ {
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect); driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
} }
else else
{ {
tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
tr.LowerRightCorner.X = 1000;
tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1; tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y; tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect); driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
} }
} }
// drawing some border and background for the tab-area.
skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment); skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment);
// enable scrollcontrols on need // enable scrollcontrols on need

View File

@ -78,9 +78,9 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
const u32 WORD_BUFFER_LENGTH = 512; const u32 WORD_BUFFER_LENGTH = 512;
core::array<core::vector3df> vertexBuffer; core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > vertexBuffer(1000);
core::array<core::vector3df> normalsBuffer; core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000);
core::array<core::vector2df> textureCoordBuffer; core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000);
SObjMtl * currMtl = new SObjMtl(); SObjMtl * currMtl = new SObjMtl();
Materials.push_back(currMtl); Materials.push_back(currMtl);
@ -101,6 +101,10 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS); bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS);
bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES); bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES);
irr::u32 lineNr = 1; // only counts non-empty lines, still useful in debugging to locate errors irr::u32 lineNr = 1; // only counts non-empty lines, still useful in debugging to locate errors
core::array<int> faceCorners;
faceCorners.reallocate(32); // should be large enough
const core::stringc TAG_OFF = "off";
while(bufPtr != bufEnd) while(bufPtr != bufEnd)
{ {
switch(bufPtr[0]) switch(bufPtr[0])
@ -173,7 +177,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
#ifdef _IRR_DEBUG_OBJ_LOADER_ #ifdef _IRR_DEBUG_OBJ_LOADER_
os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG); os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG);
#endif #endif
if (core::stringc("off")==smooth) if (TAG_OFF==smooth)
smoothingGroup=0; smoothingGroup=0;
else else
smoothingGroup=core::strtoul10(smooth); smoothingGroup=core::strtoul10(smooth);
@ -215,8 +219,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
const c8* linePtr = wordBuffer.c_str(); const c8* linePtr = wordBuffer.c_str();
const c8* const endPtr = linePtr+wordBuffer.size(); const c8* const endPtr = linePtr+wordBuffer.size();
core::array<int> faceCorners; faceCorners.set_used(0); // fast clear
faceCorners.reallocate(32); // should be large enough
// read in all vertices // read in all vertices
linePtr = goNextWord(linePtr, endPtr); linePtr = goNextWord(linePtr, endPtr);
@ -279,8 +282,6 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
currMtl->Meshbuffer->Indices.push_back( faceCorners[i] ); currMtl->Meshbuffer->Indices.push_back( faceCorners[i] );
currMtl->Meshbuffer->Indices.push_back( faceCorners[0] ); currMtl->Meshbuffer->Indices.push_back( faceCorners[0] );
} }
faceCorners.set_used(0); // fast clear
faceCorners.reallocate(32);
} }
break; break;

View File

@ -1798,11 +1798,7 @@ COGLES2Driver::~COGLES2Driver()
} }
// Color Mask // Color Mask
CacheHandler->setColorMask( CacheHandler->setColorMask(material.ColorMask);
(material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE);
// Blend Equation // Blend Equation
if (material.BlendOperation == EBO_NONE) if (material.BlendOperation == EBO_NONE)
@ -2122,7 +2118,7 @@ COGLES2Driver::~COGLES2Driver()
if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY)))
{ {
CacheHandler->setColorMask(false, false, false, false); CacheHandler->setColorMask(ECP_NONE);
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
} }
@ -2191,7 +2187,7 @@ COGLES2Driver::~COGLES2Driver()
setRenderStates2DMode(true, false, false); setRenderStates2DMode(true, false, false);
CacheHandler->setDepthMask(false); CacheHandler->setDepthMask(false);
CacheHandler->setColorMask(true, true, true, true); CacheHandler->setColorMask(ECP_ALL);
CacheHandler->setBlend(true); CacheHandler->setBlend(true);
CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -2447,10 +2443,15 @@ COGLES2Driver::~COGLES2Driver()
void COGLES2Driver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) void COGLES2Driver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
{ {
GLbitfield mask = 0; GLbitfield mask = 0;
u8 colorMask = 0;
bool depthMask = false;
CacheHandler->getColorMask(colorMask);
CacheHandler->getDepthMask(depthMask);
if (flag & ECBF_COLOR) if (flag & ECBF_COLOR)
{ {
CacheHandler->setColorMask(true, true, true, true); CacheHandler->setColorMask(ECP_ALL);
const f32 inv = 1.0f / 255.0f; const f32 inv = 1.0f / 255.0f;
glClearColor(color.getRed() * inv, color.getGreen() * inv, glClearColor(color.getRed() * inv, color.getGreen() * inv,
@ -2474,6 +2475,9 @@ COGLES2Driver::~COGLES2Driver()
if (mask) if (mask)
glClear(mask); glClear(mask);
CacheHandler->setColorMask(colorMask);
CacheHandler->setDepthMask(depthMask);
} }

View File

@ -170,10 +170,10 @@ class COpenGLCoreCacheHandler
public: public:
COpenGLCoreCacheHandler(TOpenGLDriver* driver) : COpenGLCoreCacheHandler(TOpenGLDriver* driver) :
Driver(driver), TextureCache(STextureCache(this, Driver->getFeature().TextureUnit)), FrameBufferCount(0), Driver(driver), TextureCache(STextureCache(this, Driver->getFeature().TextureUnit)), FrameBufferCount(0), BlendEquation(0), BlendSourceRGB(0),
BlendEquation(0), BlendSourceRGB(0), BlendDestinationRGB(0), BlendSourceAlpha(0), BlendDestinationAlpha(0), BlendDestinationRGB(0), BlendSourceAlpha(0), BlendDestinationAlpha(0), Blend(0), BlendEquationInvalid(false), BlendFuncInvalid(false), BlendInvalid(false),
Blend(0), ColorMask(0), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true), ColorMask(0), ColorMaskInvalid(false), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true), DepthTest(false), FrameBufferID(0),
DepthTest(false), FrameBufferID(0), ProgramID(0), ActiveTexture(GL_TEXTURE0), ViewportX(0), ViewportY(0) ProgramID(0), ActiveTexture(GL_TEXTURE0), ViewportX(0), ViewportY(0)
{ {
const COpenGLCoreFeature& feature = Driver->getFeature(); const COpenGLCoreFeature& feature = Driver->getFeature();
@ -185,8 +185,7 @@ public:
BlendSourceAlpha = new GLenum[FrameBufferCount]; BlendSourceAlpha = new GLenum[FrameBufferCount];
BlendDestinationAlpha = new GLenum[FrameBufferCount]; BlendDestinationAlpha = new GLenum[FrameBufferCount];
Blend = new bool[FrameBufferCount]; Blend = new bool[FrameBufferCount];
ColorMask = new u8[FrameBufferCount];
ColorMask = new bool[FrameBufferCount][4];
// Initial OpenGL values from specification. // Initial OpenGL values from specification.
@ -205,9 +204,7 @@ public:
BlendDestinationAlpha[i] = GL_ZERO; BlendDestinationAlpha[i] = GL_ZERO;
Blend[i] = false; Blend[i] = false;
ColorMask[i] = ECP_ALL;
for (u32 j = 0; j < 4; ++j)
ColorMask[i][j] = true;
} }
glBlendFunc(GL_ONE, GL_ZERO); glBlendFunc(GL_ONE, GL_ZERO);
@ -260,12 +257,14 @@ public:
void setBlendEquation(GLenum mode) void setBlendEquation(GLenum mode)
{ {
if (BlendEquation[0] != mode) if (BlendEquation[0] != mode || BlendEquationInvalid)
{ {
Driver->irrGlBlendEquation(mode); Driver->irrGlBlendEquation(mode);
for (GLuint i = 0; i < FrameBufferCount; ++i) for (GLuint i = 0; i < FrameBufferCount; ++i)
BlendEquation[i] = mode; BlendEquation[i] = mode;
BlendEquationInvalid = false;
} }
} }
@ -276,13 +275,15 @@ public:
Driver->irrGlBlendEquationIndexed(index, mode); Driver->irrGlBlendEquationIndexed(index, mode);
BlendEquation[index] = mode; BlendEquation[index] = mode;
BlendEquationInvalid = true;
} }
} }
void setBlendFunc(GLenum source, GLenum destination) void setBlendFunc(GLenum source, GLenum destination)
{ {
if (BlendSourceRGB[0] != source || BlendDestinationRGB[0] != destination || if (BlendSourceRGB[0] != source || BlendDestinationRGB[0] != destination ||
BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination) BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination ||
BlendFuncInvalid)
{ {
glBlendFunc(source, destination); glBlendFunc(source, destination);
@ -293,6 +294,8 @@ public:
BlendSourceAlpha[i] = source; BlendSourceAlpha[i] = source;
BlendDestinationAlpha[i] = destination; BlendDestinationAlpha[i] = destination;
} }
BlendFuncInvalid = false;
} }
} }
@ -301,7 +304,8 @@ public:
if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha) if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha)
{ {
if (BlendSourceRGB[0] != sourceRGB || BlendDestinationRGB[0] != destinationRGB || if (BlendSourceRGB[0] != sourceRGB || BlendDestinationRGB[0] != destinationRGB ||
BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha) BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha ||
BlendFuncInvalid)
{ {
Driver->irrGlBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha); Driver->irrGlBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha);
@ -312,6 +316,8 @@ public:
BlendSourceAlpha[i] = sourceAlpha; BlendSourceAlpha[i] = sourceAlpha;
BlendDestinationAlpha[i] = destinationAlpha; BlendDestinationAlpha[i] = destinationAlpha;
} }
BlendFuncInvalid = false;
} }
} }
else else
@ -331,6 +337,7 @@ public:
BlendDestinationRGB[index] = destination; BlendDestinationRGB[index] = destination;
BlendSourceAlpha[index] = source; BlendSourceAlpha[index] = source;
BlendDestinationAlpha[index] = destination; BlendDestinationAlpha[index] = destination;
BlendFuncInvalid = true;
} }
} }
@ -347,6 +354,7 @@ public:
BlendDestinationRGB[index] = destinationRGB; BlendDestinationRGB[index] = destinationRGB;
BlendSourceAlpha[index] = sourceAlpha; BlendSourceAlpha[index] = sourceAlpha;
BlendDestinationAlpha[index] = destinationAlpha; BlendDestinationAlpha[index] = destinationAlpha;
BlendFuncInvalid = true;
} }
} }
else else
@ -357,7 +365,7 @@ public:
void setBlend(bool enable) void setBlend(bool enable)
{ {
if (Blend[0] != enable) if (Blend[0] != enable || BlendInvalid)
{ {
if (enable) if (enable)
glEnable(GL_BLEND); glEnable(GL_BLEND);
@ -366,6 +374,8 @@ public:
for (GLuint i = 0; i < FrameBufferCount; ++i) for (GLuint i = 0; i < FrameBufferCount; ++i)
Blend[i] = enable; Blend[i] = enable;
BlendInvalid = false;
} }
} }
@ -379,37 +389,38 @@ public:
Driver->irrGlDisableIndexed(GL_BLEND, index); Driver->irrGlDisableIndexed(GL_BLEND, index);
Blend[index] = enable; Blend[index] = enable;
BlendInvalid = true;
} }
} }
// Color Mask. // Color Mask.
void setColorMask(bool red, bool green, bool blue, bool alpha) void getColorMask(u8& mask)
{ {
if (ColorMask[0][0] != red || ColorMask[0][1] != green || ColorMask[0][2] != blue || ColorMask[0][3] != alpha) mask = ColorMask[0];
}
void setColorMask(u8 mask)
{
if (ColorMask[0] != mask || ColorMaskInvalid)
{ {
glColorMask(red, green, blue, alpha); glColorMask((mask & ECP_RED) ? GL_TRUE : GL_FALSE, (mask & ECP_GREEN) ? GL_TRUE : GL_FALSE, (mask & ECP_BLUE) ? GL_TRUE : GL_FALSE, (mask & ECP_ALPHA) ? GL_TRUE : GL_FALSE);
for (GLuint i = 0; i < FrameBufferCount; ++i) for (GLuint i = 0; i < FrameBufferCount; ++i)
{ ColorMask[i] = mask;
ColorMask[i][0] = red;
ColorMask[i][1] = green; ColorMaskInvalid = false;
ColorMask[i][2] = blue;
ColorMask[i][3] = alpha;
}
} }
} }
void setColorMaskIndexed(GLuint index, bool red, bool green, bool blue, bool alpha) void setColorMaskIndexed(GLuint index, u8 mask)
{ {
if (index < FrameBufferCount && (ColorMask[index][0] != red || ColorMask[index][1] != green || ColorMask[index][2] != blue || ColorMask[index][3] != alpha)) if (index < FrameBufferCount && ColorMask[index] != mask)
{ {
Driver->irrGlColorMaskIndexed(index, red, green, blue, alpha); Driver->irrGlColorMaskIndexed(index, (mask & ECP_RED) ? GL_TRUE : GL_FALSE, (mask & ECP_GREEN) ? GL_TRUE : GL_FALSE, (mask & ECP_BLUE) ? GL_TRUE : GL_FALSE, (mask & ECP_ALPHA) ? GL_TRUE : GL_FALSE);
ColorMask[index][0] = red; ColorMask[index] = mask;
ColorMask[index][1] = green; ColorMaskInvalid = true;
ColorMask[index][2] = blue;
ColorMask[index][3] = alpha;
} }
} }
@ -432,6 +443,7 @@ public:
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
else else
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
CullFace = enable; CullFace = enable;
} }
} }
@ -447,6 +459,11 @@ public:
} }
} }
void getDepthMask(bool& depth)
{
depth = DepthMask;
}
void setDepthMask(bool enable) void setDepthMask(bool enable)
{ {
if (DepthMask != enable) if (DepthMask != enable)
@ -455,6 +472,7 @@ public:
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
else else
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
DepthMask = enable; DepthMask = enable;
} }
} }
@ -467,6 +485,7 @@ public:
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
else else
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
DepthTest = enable; DepthTest = enable;
} }
} }
@ -554,8 +573,13 @@ protected:
GLenum* BlendSourceAlpha; GLenum* BlendSourceAlpha;
GLenum* BlendDestinationAlpha; GLenum* BlendDestinationAlpha;
bool* Blend; bool* Blend;
bool BlendEquationInvalid;
bool BlendFuncInvalid;
bool BlendInvalid;
bool(*ColorMask)[4]; u8* ColorMask;
bool ColorMaskInvalid;
GLenum CullFaceMode; GLenum CullFaceMode;
bool CullFace; bool CullFace;

View File

@ -467,7 +467,7 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
extGlBindBuffer(GL_ARRAY_BUFFER, 0); extGlBindBuffer(GL_ARRAY_BUFFER, 0);
return (!testGLError()); return (!testGLError(__LINE__));
#else #else
return false; return false;
#endif #endif
@ -541,7 +541,7 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return (!testGLError()); return (!testGLError(__LINE__));
#else #else
return false; return false;
#endif #endif
@ -735,10 +735,7 @@ void COpenGLDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
#else #else
0); 0);
#endif #endif
if ( testGLError() ) testGLError(__LINE__);
{
os::Printer::log("Occlusion Query failed", ELL_ERROR);
}
} }
} }
@ -766,10 +763,7 @@ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
0, 0,
#endif #endif
&available); &available);
if ( testGLError() ) testGLError(__LINE__);
{
os::Printer::log("extGlGetQueryObjectiv failed", ELL_ERROR);
}
} }
if (available==GL_TRUE) if (available==GL_TRUE)
{ {
@ -785,10 +779,7 @@ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
if (queryFeature(EVDF_OCCLUSION_QUERY)) if (queryFeature(EVDF_OCCLUSION_QUERY))
OcclusionQueries[index].Result = available; OcclusionQueries[index].Result = available;
} }
if ( testGLError() ) testGLError(__LINE__);
{
os::Printer::log("extGlGetQueryObjectiv failed", ELL_ERROR);
}
} }
} }
@ -1295,87 +1286,24 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi
if (!sourceRect.isValid()) if (!sourceRect.isValid())
return; return;
core::position2d<s32> targetPos(destPos); // clip these coordinates
core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner); core::rect<s32> targetRect(destPos, sourceRect.getSize());
// This needs to be signed as it may go negative.
core::dimension2d<s32> sourceSize(sourceRect.getSize());
if (clipRect) if (clipRect)
{ {
if (targetPos.X < clipRect->UpperLeftCorner.X) targetRect.clipAgainst(*clipRect);
{ if ( targetRect.getWidth() < 0 || targetRect.getHeight() < 0 )
sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
if (sourceSize.Width <= 0)
return;
sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
targetPos.X = clipRect->UpperLeftCorner.X;
}
if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
if (sourceSize.Width <= 0)
return;
}
if (targetPos.Y < clipRect->UpperLeftCorner.Y)
{
sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
if (sourceSize.Height <= 0)
return;
sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
targetPos.Y = clipRect->UpperLeftCorner.Y;
}
if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
if (sourceSize.Height <= 0)
return;
}
}
// clip these coordinates
if (targetPos.X<0)
{
sourceSize.Width += targetPos.X;
if (sourceSize.Width <= 0)
return; return;
sourcePos.X -= targetPos.X;
targetPos.X = 0;
} }
const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
targetRect.clipAgainst( core::rect<s32>(0,0, (s32)renderTargetSize.Width, (s32)renderTargetSize.Height) );
if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) if ( targetRect.getWidth() < 0 || targetRect.getHeight() < 0 )
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
if (sourceSize.Width <= 0)
return; return;
}
if (targetPos.Y<0)
{
sourceSize.Height += targetPos.Y;
if (sourceSize.Height <= 0)
return;
sourcePos.Y -= targetPos.Y;
targetPos.Y = 0;
}
if (targetPos.Y + sourceSize.Height >(s32)renderTargetSize.Height)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
if (sourceSize.Height <= 0)
return;
}
// ok, we've clipped everything. // ok, we've clipped everything.
// now draw it. // now draw it.
const core::dimension2d<s32> sourceSize(targetRect.getSize());
const core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner + (targetRect.UpperLeftCorner-destPos));
const core::dimension2d<u32>& ss = texture->getOriginalSize(); const core::dimension2d<u32>& ss = texture->getOriginalSize();
const f32 invW = 1.f / static_cast<f32>(ss.Width); const f32 invW = 1.f / static_cast<f32>(ss.Width);
@ -1386,8 +1314,6 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi
(sourcePos.X + sourceSize.Width) * invW, (sourcePos.X + sourceSize.Width) * invW,
(sourcePos.Y + sourceSize.Height) * invH); (sourcePos.Y + sourceSize.Height) * invH);
const core::rect<s32> poss(targetPos, sourceSize);
disableTextures(1); disableTextures(1);
if (!CacheHandler->getTextureCache().set(0, texture)) if (!CacheHandler->getTextureCache().set(0, texture))
return; return;
@ -1398,10 +1324,10 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi
Quad2DVertices[2].Color = color; Quad2DVertices[2].Color = color;
Quad2DVertices[3].Color = color; Quad2DVertices[3].Color = color;
Quad2DVertices[0].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f); Quad2DVertices[0].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[1].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f); Quad2DVertices[1].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f);
Quad2DVertices[2].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f); Quad2DVertices[2].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f);
Quad2DVertices[3].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f); Quad2DVertices[3].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f);
Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
@ -2111,7 +2037,7 @@ void COpenGLDriver::setMaterial(const SMaterial& material)
//! prints error if an error happened. //! prints error if an error happened.
bool COpenGLDriver::testGLError() bool COpenGLDriver::testGLError(int code)
{ {
#ifdef _DEBUG #ifdef _DEBUG
GLenum g = glGetError(); GLenum g = glGetError();
@ -2120,22 +2046,22 @@ bool COpenGLDriver::testGLError()
case GL_NO_ERROR: case GL_NO_ERROR:
return false; return false;
case GL_INVALID_ENUM: case GL_INVALID_ENUM:
os::Printer::log("GL_INVALID_ENUM", ELL_ERROR); break; os::Printer::log("GL_INVALID_ENUM", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_INVALID_VALUE: case GL_INVALID_VALUE:
os::Printer::log("GL_INVALID_VALUE", ELL_ERROR); break; os::Printer::log("GL_INVALID_VALUE", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_INVALID_OPERATION: case GL_INVALID_OPERATION:
os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR); break; os::Printer::log("GL_INVALID_OPERATION", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_STACK_OVERFLOW: case GL_STACK_OVERFLOW:
os::Printer::log("GL_STACK_OVERFLOW", ELL_ERROR); break; os::Printer::log("GL_STACK_OVERFLOW", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_STACK_UNDERFLOW: case GL_STACK_UNDERFLOW:
os::Printer::log("GL_STACK_UNDERFLOW", ELL_ERROR); break; os::Printer::log("GL_STACK_UNDERFLOW", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_OUT_OF_MEMORY: case GL_OUT_OF_MEMORY:
os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR); break; os::Printer::log("GL_OUT_OF_MEMORY", core::stringc(code).c_str(), ELL_ERROR); break;
case GL_TABLE_TOO_LARGE: case GL_TABLE_TOO_LARGE:
os::Printer::log("GL_TABLE_TOO_LARGE", ELL_ERROR); break; os::Printer::log("GL_TABLE_TOO_LARGE", core::stringc(code).c_str(), ELL_ERROR); break;
#if defined(GL_EXT_framebuffer_object) #if defined(GL_EXT_framebuffer_object)
case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", ELL_ERROR); break; os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", core::stringc(code).c_str(), ELL_ERROR); break;
#endif #endif
}; };
// _IRR_DEBUG_BREAK_IF(true); // _IRR_DEBUG_BREAK_IF(true);
@ -2540,11 +2466,7 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
} }
// Color Mask // Color Mask
CacheHandler->setColorMask( CacheHandler->setColorMask(material.ColorMask);
(material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE,
(material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE);
// Blend Equation // Blend Equation
if (material.BlendOperation == EBO_NONE) if (material.BlendOperation == EBO_NONE)
@ -3903,10 +3825,15 @@ bool COpenGLDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SCol
void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
{ {
GLbitfield mask = 0; GLbitfield mask = 0;
u8 colorMask = 0;
bool depthMask = false;
CacheHandler->getColorMask(colorMask);
CacheHandler->getDepthMask(depthMask);
if (flag & ECBF_COLOR) if (flag & ECBF_COLOR)
{ {
CacheHandler->setColorMask(true, true, true, true); CacheHandler->setColorMask(ECP_ALL);
const f32 inv = 1.0f / 255.0f; const f32 inv = 1.0f / 255.0f;
glClearColor(color.getRed() * inv, color.getGreen() * inv, glClearColor(color.getRed() * inv, color.getGreen() * inv,
@ -3930,6 +3857,9 @@ void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
if (mask) if (mask)
glClear(mask); glClear(mask);
CacheHandler->setColorMask(colorMask);
CacheHandler->setDepthMask(depthMask);
} }
@ -4004,10 +3934,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE
} }
glReadBuffer(tgt); glReadBuffer(tgt);
glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels); glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels);
if ( testGLError() ) testGLError(__LINE__);
{
os::Printer::log("glReadPixels failed", ELL_ERROR);
}
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
} }
@ -4043,7 +3970,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE
if (newImage) if (newImage)
{ {
if (testGLError() || !pixels) if (testGLError(__LINE__) || !pixels)
{ {
os::Printer::log("createScreenShot failed", ELL_ERROR); os::Printer::log("createScreenShot failed", ELL_ERROR);
newImage->drop(); newImage->drop();

View File

@ -345,9 +345,9 @@ namespace video
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) _IRR_OVERRIDE_; virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) _IRR_OVERRIDE_;
//! checks if an OpenGL error has happend and prints it //! checks if an OpenGL error has happened and prints it (+ some internal code which is usually the line number)
//! for performance reasons only available in debug mode //! for performance reasons only available in debug mode
bool testGLError(); bool testGLError(int code=0);
//! Set/unset a clipping plane. //! Set/unset a clipping plane.
//! There are at least 6 clipping planes available for the user to set at will. //! There are at least 6 clipping planes available for the user to set at will.

View File

@ -696,7 +696,7 @@ void CWebGL1Driver::drawStencilShadow(bool clearStencilBuffer,
lockRenderStateMode(); lockRenderStateMode();
CacheHandler->setDepthMask(false); CacheHandler->setDepthMask(false);
CacheHandler->setColorMask(true, true, true, true); CacheHandler->setColorMask(ECP_ALL);
CacheHandler->setBlend(true); CacheHandler->setBlend(true);
CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);