mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Kill off the GL state cache
This commit is contained in:
parent
f3282dcfda
commit
51f467a7b3
22 changed files with 110 additions and 437 deletions
|
@ -887,8 +887,6 @@ add_library(native STATIC
|
|||
ext/native/file/vfs.h
|
||||
ext/native/file/zip_read.cpp
|
||||
ext/native/file/zip_read.h
|
||||
ext/native/gfx/GLStateCache.cpp
|
||||
ext/native/gfx/GLStateCache.h
|
||||
ext/native/gfx/gl_common.h
|
||||
ext/native/gfx/gl_debug_log.cpp
|
||||
ext/native/gfx/gl_debug_log.h
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "Core/Reporting.h"
|
||||
#include "DepalettizeShaderGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/Common/DepalettizeShaderCommon.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/FragmentTestCacheGLES.h"
|
||||
#include "GPU/GLES/StateMappingGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
|
@ -585,7 +584,7 @@ rotateVBO:
|
|||
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
|
||||
}
|
||||
|
||||
ApplyDrawStateLate();
|
||||
ApplyDrawStateLate(false, 0);
|
||||
|
||||
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
|
||||
GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt());
|
||||
|
@ -646,14 +645,11 @@ rotateVBO:
|
|||
prim, vertexCount,
|
||||
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
|
||||
maxIndex, drawBuffer, numTrans, drawIndexed, ¶ms, &result);
|
||||
ApplyDrawStateLate();
|
||||
ApplyDrawStateLate(result.setStencil, result.stencilValue);
|
||||
|
||||
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
|
||||
|
||||
if (result.action == SW_DRAW_PRIMITIVES) {
|
||||
if (result.setStencil) {
|
||||
glstate.stencilFunc.set(GL_ALWAYS, result.stencilValue, 255);
|
||||
}
|
||||
const int vertexSize = sizeof(transformed[0]);
|
||||
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
|
|
|
@ -165,7 +165,7 @@ private:
|
|||
|
||||
void DoFlush();
|
||||
void ApplyDrawState(int prim);
|
||||
void ApplyDrawStateLate();
|
||||
void ApplyDrawStateLate(bool setStencil, int stencilValue);
|
||||
void ResetShaderBlending();
|
||||
|
||||
GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include <map>
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
|
||||
#include "GPU/ge_constants.h"
|
||||
|
|
|
@ -1058,6 +1058,7 @@ void FramebufferManagerGLES::DestroyAllFBOs() {
|
|||
void FramebufferManagerGLES::Resized() {
|
||||
FramebufferManagerCommon::Resized();
|
||||
|
||||
render_->Resize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
|
||||
if (UpdateSize()) {
|
||||
DestroyAllFBOs();
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "GPU/GeDisasm.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/GPU_GLES.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
|
@ -160,9 +159,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
// Update again after init to be sure of any silly driver problems.
|
||||
UpdateVsyncInterval(true);
|
||||
|
||||
// Some of our defaults are different from hw defaults, let's assert them.
|
||||
// We restore each frame anyway, but here is convenient for tests.
|
||||
glstate.Restore();
|
||||
textureCacheGL_->NotifyConfigChanged();
|
||||
|
||||
// Load shader cache.
|
||||
|
@ -431,14 +427,6 @@ void GPU_GLES::Reinitialize() {
|
|||
}
|
||||
|
||||
void GPU_GLES::InitClear() {
|
||||
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
|
||||
if (useNonBufferedRendering) {
|
||||
glstate.depthWrite.set(GL_TRUE);
|
||||
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glClearColor(0,0,0,1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
|
||||
}
|
||||
|
||||
void GPU_GLES::BeginHostFrame() {
|
||||
|
@ -497,7 +485,6 @@ void GPU_GLES::UpdateCmdInfo() {
|
|||
}
|
||||
|
||||
void GPU_GLES::ReapplyGfxState() {
|
||||
glstate.Restore();
|
||||
GPUCommon::ReapplyGfxState();
|
||||
}
|
||||
|
||||
|
@ -557,9 +544,6 @@ void GPU_GLES::CopyDisplayToOutput() {
|
|||
|
||||
shaderManagerGL_->DirtyLastShader();
|
||||
|
||||
glstate.depthWrite.set(GL_TRUE);
|
||||
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
framebufferManagerGL_->CopyDisplayToOutput();
|
||||
framebufferManagerGL_->EndFrame();
|
||||
|
||||
|
@ -768,8 +752,6 @@ void GPU_GLES::ClearShaderCache() {
|
|||
void GPU_GLES::CleanupBeforeUI() {
|
||||
// Clear any enabled vertex arrays.
|
||||
shaderManagerGL_->DirtyLastShader();
|
||||
glstate.arrayBuffer.bind(0);
|
||||
glstate.elementArrayBuffer.bind(0);
|
||||
}
|
||||
|
||||
void GPU_GLES::DoState(PointerWrap &p) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "base/logging.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "gfx/gl_debug_log.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "thin3d/GLRenderManager.h"
|
||||
#include "i18n/i18n.h"
|
||||
#include "math/math_util.h"
|
||||
|
@ -39,7 +40,6 @@
|
|||
#include "GPU/Math3D.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
#include "FramebufferManagerGLES.h"
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/GLES/GPU_GLES.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
|
@ -169,12 +168,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
bool colorMask = gstate.isClearModeColorMask();
|
||||
bool alphaMask = gstate.isClearModeAlphaMask();
|
||||
renderManager->SetNoBlendAndMask((colorMask ? 7 : 0) | (alphaMask ? 8 : 0));
|
||||
#ifndef USING_GLES2
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) {
|
||||
// Logic Ops
|
||||
glstate.colorLogicOp.disable();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Do the large chunks of state conversion. We might be able to hide these two behind a dirty-flag each,
|
||||
// to avoid recomputing heavy stuff unnecessarily every draw call.
|
||||
|
@ -280,7 +273,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
if (gstate.isClearModeDepthMask()) {
|
||||
framebufferManager_->SetDepthUpdated();
|
||||
}
|
||||
renderManager->SetStencil(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, GL_REPLACE, GL_REPLACE, GL_REPLACE, 0xFF, 0xFF, 0xFF);
|
||||
renderManager->SetStencilFunc(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, 0xFF, 0xFF);
|
||||
renderManager->SetStencilOp(0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS);
|
||||
} else {
|
||||
// Depth Test
|
||||
|
@ -293,9 +287,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
ConvertStencilFuncState(stencilState);
|
||||
// Stencil Test
|
||||
if (stencilState.enabled) {
|
||||
renderManager->SetStencil(stencilState.enabled, compareOps[stencilState.testFunc],
|
||||
stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass],
|
||||
stencilState.writeMask, stencilState.testMask, stencilState.testRef);
|
||||
renderManager->SetStencilFunc(stencilState.enabled, compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask);
|
||||
renderManager->SetStencilOp(stencilState.writeMask, stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]);
|
||||
} else {
|
||||
renderManager->SetStencilDisabled();
|
||||
}
|
||||
|
@ -332,7 +325,11 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
}
|
||||
}
|
||||
|
||||
void DrawEngineGLES::ApplyDrawStateLate() {
|
||||
void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) {
|
||||
if (setStencil) {
|
||||
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, stencilValue, 255);
|
||||
}
|
||||
|
||||
// At this point, we know if the vertices are full alpha or not.
|
||||
// TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)?
|
||||
if (!gstate.isModeClear()) {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "gfx_es2/glsl_program.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/Common/StencilCommon.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
|
@ -111,12 +110,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
}
|
||||
|
||||
// Let's not bother with the shader if it's just zero.
|
||||
glstate.scissorTest.disable();
|
||||
glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
return true;
|
||||
}
|
||||
|
@ -150,8 +144,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
|
||||
DisableState();
|
||||
render_->SetNoBlendAndMask(0x8);
|
||||
glstate.stencilTest.enable();
|
||||
glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
|
||||
bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT);
|
||||
|
||||
|
@ -178,7 +170,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
textureCacheGL_->ForgetLastTexture();
|
||||
|
||||
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT);
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF);
|
||||
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF);
|
||||
|
||||
for (int i = 1; i < values; i += i) {
|
||||
if (!(usedBits & i)) {
|
||||
|
@ -186,18 +178,17 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
continue;
|
||||
}
|
||||
if (dstBuffer->format == GE_FORMAT_4444) {
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, (i << 4) | i, 0xFF, 0xFF);
|
||||
render_->SetStencilOp((i << 4) | i, GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f));
|
||||
} else if (dstBuffer->format == GE_FORMAT_5551) {
|
||||
glstate.stencilMask.set(0xFF);
|
||||
render_->SetStencilOp(0xFF, GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f));
|
||||
} else {
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, i, 0xFF, 0xFF);
|
||||
render_->SetStencilOp(i, GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f));
|
||||
}
|
||||
DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST);
|
||||
}
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
if (useBlit) {
|
||||
draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST);
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "Core/Reporting.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/FragmentShaderGeneratorGLES.h"
|
||||
|
@ -523,6 +522,10 @@ GLenum ToGLESFormat(ReplacedTextureFormat fmt) {
|
|||
void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImages) {
|
||||
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
|
||||
|
||||
// Never replace images in-place - there's no such thing, drivers have to fake it anyway, at least if
|
||||
// the image has been in use within the last frame or two.
|
||||
replaceImages = false;
|
||||
|
||||
// For the estimate, we assume cluts always point to 8888 for simplicity.
|
||||
cacheSizeEstimate_ += EstimateTexMemoryUsage(entry);
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "debugger_memorytex.h"
|
||||
#include "gfx/GLStateCache.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "ui_debugger_memorytex.h"
|
||||
#include "Core/MemMap.h"
|
||||
|
|
|
@ -75,7 +75,6 @@ LOCAL_SRC_FILES :=\
|
|||
gfx_es2/draw_buffer.cpp.arm \
|
||||
gfx_es2/draw_text.cpp.arm \
|
||||
gfx_es2/draw_text_android.cpp.arm \
|
||||
gfx/GLStateCache.cpp.arm \
|
||||
gfx/gl_debug_log.cpp \
|
||||
gfx/texture_atlas.cpp \
|
||||
image/zim_load.cpp \
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
#include "gfx/GLStateCache.h"
|
||||
|
||||
OpenGLState glstate;
|
||||
|
||||
int OpenGLState::state_count = 0;
|
||||
|
||||
void OpenGLState::Restore() {
|
||||
int count = 0;
|
||||
|
||||
blend.restore(); count++;
|
||||
blendEquationSeparate.restore(); count++;
|
||||
blendFuncSeparate.restore(); count++;
|
||||
blendColor.restore(); count++;
|
||||
|
||||
scissorTest.restore(); count++;
|
||||
scissorRect.restore(); count++;
|
||||
|
||||
cullFace.restore(); count++;
|
||||
cullFaceMode.restore(); count++;
|
||||
frontFace.restore(); count++;
|
||||
|
||||
depthTest.restore(); count++;
|
||||
depthRange.restore(); count++;
|
||||
depthFunc.restore(); count++;
|
||||
depthWrite.restore(); count++;
|
||||
|
||||
colorMask.restore(); count++;
|
||||
viewport.restore(); count++;
|
||||
|
||||
stencilTest.restore(); count++;
|
||||
stencilOp.restore(); count++;
|
||||
stencilFunc.restore(); count++;
|
||||
stencilMask.restore(); count++;
|
||||
|
||||
dither.restore(); count++;
|
||||
|
||||
#if !defined(USING_GLES2)
|
||||
colorLogicOp.restore(); count++;
|
||||
logicOp.restore(); count++;
|
||||
#endif
|
||||
|
||||
arrayBuffer.restore(); count++;
|
||||
elementArrayBuffer.restore(); count++;
|
||||
|
||||
if (count != state_count) {
|
||||
FLOG("OpenGLState::Restore is missing some states");
|
||||
}
|
||||
}
|
|
@ -1,283 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <cstring> // for memcmp
|
||||
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
|
||||
// OpenGL state cache.
|
||||
// Probably only really worth it in rendering cores on weak mobile hardware.
|
||||
class OpenGLState {
|
||||
private:
|
||||
template<GLenum cap, bool init>
|
||||
class BoolState {
|
||||
private:
|
||||
bool v;
|
||||
public:
|
||||
BoolState() : v(init) {
|
||||
OpenGLState::state_count++;
|
||||
}
|
||||
|
||||
inline void set(bool value) {
|
||||
if (value != v) {
|
||||
v = value;
|
||||
restore();
|
||||
}
|
||||
}
|
||||
inline void force(bool value) {
|
||||
bool old = v;
|
||||
set(value);
|
||||
v = old;
|
||||
}
|
||||
inline void enable() {
|
||||
set(true);
|
||||
}
|
||||
inline void disable() {
|
||||
set(false);
|
||||
}
|
||||
operator bool() const {
|
||||
return isset();
|
||||
}
|
||||
inline bool isset() {
|
||||
return v;
|
||||
}
|
||||
void restore() {
|
||||
if (v)
|
||||
glEnable(cap);
|
||||
else
|
||||
glDisable(cap);
|
||||
}
|
||||
};
|
||||
|
||||
#define STATE1(func, p1type, p1def) \
|
||||
class SavedState1_##func { \
|
||||
p1type p1; \
|
||||
public: \
|
||||
SavedState1_##func() : p1(p1def) { \
|
||||
OpenGLState::state_count++; \
|
||||
} \
|
||||
void set(p1type newp1) { \
|
||||
if (newp1 != p1) { \
|
||||
p1 = newp1; \
|
||||
restore(); \
|
||||
} \
|
||||
} \
|
||||
void force(p1type newp1) { \
|
||||
p1type old = p1; \
|
||||
set(newp1); \
|
||||
p1 = old; \
|
||||
} \
|
||||
inline void restore() { \
|
||||
func(p1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define STATE2(func, p1type, p2type, p1def, p2def) \
|
||||
class SavedState2_##func { \
|
||||
p1type p1; \
|
||||
p2type p2; \
|
||||
public: \
|
||||
SavedState2_##func() : p1(p1def), p2(p2def) { \
|
||||
OpenGLState::state_count++; \
|
||||
} \
|
||||
inline void set(p1type newp1, p2type newp2) { \
|
||||
if (newp1 != p1 || newp2 != p2) { \
|
||||
p1 = newp1; \
|
||||
p2 = newp2; \
|
||||
restore(); \
|
||||
} \
|
||||
} \
|
||||
void force(p1type newp1, p2type newp2) { \
|
||||
p1type old1 = p1; \
|
||||
p2type old2 = p2; \
|
||||
set(newp1, newp2); \
|
||||
p1 = old1; \
|
||||
p2 = old2; \
|
||||
} \
|
||||
inline void restore() { \
|
||||
func(p1, p2); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \
|
||||
class SavedState3_##func { \
|
||||
p1type p1; \
|
||||
p2type p2; \
|
||||
p3type p3; \
|
||||
public: \
|
||||
SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \
|
||||
OpenGLState::state_count++; \
|
||||
} \
|
||||
inline void set(p1type newp1, p2type newp2, p3type newp3) { \
|
||||
if (newp1 != p1 || newp2 != p2 || newp3 != p3) { \
|
||||
p1 = newp1; \
|
||||
p2 = newp2; \
|
||||
p3 = newp3; \
|
||||
restore(); \
|
||||
} \
|
||||
} \
|
||||
void force(p1type newp1, p2type newp2, p3type newp3) { \
|
||||
p1type old1 = p1; \
|
||||
p2type old2 = p2; \
|
||||
p3type old3 = p3; \
|
||||
set(newp1, newp2, newp3); \
|
||||
p1 = old1; \
|
||||
p2 = old2; \
|
||||
p3 = old3; \
|
||||
} \
|
||||
inline void restore() { \
|
||||
func(p1, p2, p3); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \
|
||||
class SavedState4_##func { \
|
||||
p1type p1; \
|
||||
p2type p2; \
|
||||
p3type p3; \
|
||||
p4type p4; \
|
||||
public: \
|
||||
SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \
|
||||
OpenGLState::state_count++; \
|
||||
} \
|
||||
inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \
|
||||
if (newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \
|
||||
p1 = newp1; \
|
||||
p2 = newp2; \
|
||||
p3 = newp3; \
|
||||
p4 = newp4; \
|
||||
restore(); \
|
||||
} \
|
||||
} \
|
||||
void force(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \
|
||||
p1type old1 = p1; \
|
||||
p2type old2 = p2; \
|
||||
p3type old3 = p3; \
|
||||
p4type old4 = p4; \
|
||||
set(newp1, newp2, newp3, newp4); \
|
||||
p1 = old1; \
|
||||
p2 = old2; \
|
||||
p3 = old3; \
|
||||
p4 = old4; \
|
||||
} \
|
||||
inline void restore() { \
|
||||
func(p1, p2, p3, p4); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define STATEFLOAT4(func, def) \
|
||||
class SavedState4_##func { \
|
||||
float p[4]; \
|
||||
public: \
|
||||
SavedState4_##func() { \
|
||||
for (int i = 0; i < 4; i++) {p[i] = def;} \
|
||||
OpenGLState::state_count++; \
|
||||
} \
|
||||
inline void set(const float v[4]) { \
|
||||
if (memcmp(p, v, sizeof(float) * 4)) { \
|
||||
memcpy(p, v, sizeof(float) * 4); \
|
||||
restore(); \
|
||||
} \
|
||||
} \
|
||||
void force(const float v[4]) { \
|
||||
float old[4]; \
|
||||
memcpy(old, p, sizeof(float) * 4); \
|
||||
set(v); \
|
||||
memcpy(p, old, sizeof(float) * 4); \
|
||||
} \
|
||||
inline void restore() { \
|
||||
func(p[0], p[1], p[2], p[3]); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define STATEBIND(func, target) \
|
||||
class SavedBind_##func_##target { \
|
||||
GLuint val_; \
|
||||
public: \
|
||||
SavedBind_##func_##target() { \
|
||||
val_ = 0; \
|
||||
OpenGLState::state_count++; \
|
||||
} \
|
||||
inline void bind(GLuint val) { \
|
||||
if (val_ != val) { \
|
||||
val_ = val; \
|
||||
restore(); \
|
||||
} \
|
||||
} \
|
||||
inline void force(GLuint val) { \
|
||||
GLuint old = val_; \
|
||||
bind(val); \
|
||||
val_ = old; \
|
||||
} \
|
||||
inline void unbind() { \
|
||||
bind(0); \
|
||||
} \
|
||||
inline void restore() { \
|
||||
func(target, val_); \
|
||||
} \
|
||||
}
|
||||
|
||||
public:
|
||||
static int state_count;
|
||||
OpenGLState() {}
|
||||
void Restore();
|
||||
|
||||
// When adding a state here, don't forget to add it to OpenGLState::Restore() too
|
||||
|
||||
// Blending
|
||||
BoolState<GL_BLEND, false> blend;
|
||||
STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate;
|
||||
|
||||
// On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice)
|
||||
STATE2(glBlendEquationSeparate, GLenum, GLenum, GL_FUNC_ADD, GL_FUNC_ADD) blendEquationSeparate;
|
||||
STATEFLOAT4(glBlendColor, 1.0f) blendColor;
|
||||
|
||||
// Logic Ops. Not available on OpenGL ES at all.
|
||||
#if !defined(USING_GLES2)
|
||||
BoolState<GL_COLOR_LOGIC_OP, false> colorLogicOp;
|
||||
STATE1(glLogicOp, GLenum, GL_COPY) logicOp;
|
||||
#endif
|
||||
|
||||
// Dither
|
||||
BoolState<GL_DITHER, false> dither;
|
||||
|
||||
// Cull Face
|
||||
BoolState<GL_CULL_FACE, false> cullFace;
|
||||
STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode;
|
||||
STATE1(glFrontFace, GLenum, GL_CCW) frontFace;
|
||||
|
||||
// Depth Test
|
||||
BoolState<GL_DEPTH_TEST, false> depthTest;
|
||||
#if defined(USING_GLES2)
|
||||
STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange;
|
||||
#else
|
||||
STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange;
|
||||
#endif
|
||||
STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc;
|
||||
STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite;
|
||||
|
||||
// Color Mask
|
||||
STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask;
|
||||
|
||||
// Viewport
|
||||
STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport;
|
||||
|
||||
// Scissor Test
|
||||
BoolState<GL_SCISSOR_TEST, false> scissorTest;
|
||||
STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect;
|
||||
|
||||
// Stencil Test
|
||||
BoolState<GL_STENCIL_TEST, false> stencilTest;
|
||||
STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp;
|
||||
STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc;
|
||||
STATE1(glStencilMask, GLuint, 0xFF) stencilMask;
|
||||
|
||||
STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer;
|
||||
STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer;
|
||||
};
|
||||
|
||||
#undef STATE1
|
||||
#undef STATE2
|
||||
|
||||
extern OpenGLState glstate;
|
|
@ -232,7 +232,6 @@
|
|||
<ClInclude Include="file\free.h" />
|
||||
<ClInclude Include="gfx\d3d9_shader.h" />
|
||||
<ClInclude Include="gfx\d3d9_state.h" />
|
||||
<ClInclude Include="gfx\GLStateCache.h" />
|
||||
<ClInclude Include="gfx\gl_common.h" />
|
||||
<ClInclude Include="gfx\gl_debug_log.h" />
|
||||
<ClInclude Include="gfx\texture_atlas.h" />
|
||||
|
@ -693,7 +692,6 @@
|
|||
<ClCompile Include="file\free.cpp" />
|
||||
<ClCompile Include="gfx\d3d9_shader.cpp" />
|
||||
<ClCompile Include="gfx\d3d9_state.cpp" />
|
||||
<ClCompile Include="gfx\GLStateCache.cpp" />
|
||||
<ClCompile Include="gfx\gl_debug_log.cpp" />
|
||||
<ClCompile Include="gfx\texture_atlas.cpp" />
|
||||
<ClCompile Include="gfx_es2\draw_text_android.cpp" />
|
||||
|
|
|
@ -302,9 +302,6 @@
|
|||
<ClInclude Include="gfx\d3d9_state.h">
|
||||
<Filter>gfx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gfx\GLStateCache.h">
|
||||
<Filter>gfx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="thin3d\d3d11_loader.h">
|
||||
<Filter>thin3d</Filter>
|
||||
</ClInclude>
|
||||
|
@ -775,9 +772,6 @@
|
|||
<ClCompile Include="gfx\d3d9_state.cpp">
|
||||
<Filter>gfx</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gfx\GLStateCache.cpp">
|
||||
<Filter>gfx</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="thin3d\d3d11_loader.cpp">
|
||||
<Filter>thin3d</Filter>
|
||||
</ClCompile>
|
||||
|
@ -883,4 +877,4 @@
|
|||
<UniqueIdentifier>{06c6305a-a646-485b-85b9-645a24dd6553}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -279,13 +279,24 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
|
|||
glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]);
|
||||
break;
|
||||
case GLRRenderCommand::VIEWPORT:
|
||||
{
|
||||
float y = c.viewport.vp.y;
|
||||
if (!curFramebuffer_)
|
||||
y = curFBHeight_ - y - c.viewport.vp.h;
|
||||
|
||||
// TODO: Support FP viewports through glViewportArrays
|
||||
glViewport((GLint)c.viewport.vp.x, (GLint)c.viewport.vp.y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h);
|
||||
glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h);
|
||||
glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ);
|
||||
break;
|
||||
}
|
||||
case GLRRenderCommand::SCISSOR:
|
||||
glScissor(c.scissor.rc.x, c.scissor.rc.y, c.scissor.rc.w, c.scissor.rc.h);
|
||||
{
|
||||
int y = c.scissor.rc.y;
|
||||
if (!curFramebuffer_)
|
||||
y = curFBHeight_ - y - c.scissor.rc.h;
|
||||
glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h);
|
||||
break;
|
||||
}
|
||||
case GLRRenderCommand::UNIFORM4F:
|
||||
{
|
||||
int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
|
||||
|
@ -345,24 +356,30 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case GLRRenderCommand::STENCIL:
|
||||
if (c.stencil.enabled) {
|
||||
case GLRRenderCommand::STENCILFUNC:
|
||||
if (c.stencilFunc.enabled) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask);
|
||||
glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass);
|
||||
glStencilMask(c.stencil.writeMask);
|
||||
} else {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask);
|
||||
break;
|
||||
case GLRRenderCommand::STENCILOP:
|
||||
glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass);
|
||||
glStencilMask(c.stencilOp.writeMask);
|
||||
break;
|
||||
case GLRRenderCommand::BINDTEXTURE:
|
||||
{
|
||||
GLint target = c.texture.slot;
|
||||
if (target != activeTexture) {
|
||||
glActiveTexture(GL_TEXTURE0 + target);
|
||||
activeTexture = target;
|
||||
GLint slot = c.texture.slot;
|
||||
if (slot != activeTexture) {
|
||||
glActiveTexture(GL_TEXTURE0 + slot);
|
||||
activeTexture = slot;
|
||||
}
|
||||
if (c.texture.texture) {
|
||||
glBindTexture(c.texture.texture->target, c.texture.texture->texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // ?
|
||||
}
|
||||
glBindTexture(c.texture.texture->target, c.texture.texture->texture);
|
||||
break;
|
||||
}
|
||||
case GLRRenderCommand::BINDPROGRAM:
|
||||
|
@ -518,7 +535,13 @@ void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) {
|
|||
}
|
||||
|
||||
void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) {
|
||||
|
||||
if (pass.render.framebuffer) {
|
||||
curFBWidth_ = pass.render.framebuffer->width;
|
||||
curFBHeight_ = pass.render.framebuffer->height;
|
||||
} else {
|
||||
curFBWidth_ = targetWidth_;
|
||||
curFBHeight_ = targetHeight_;
|
||||
}
|
||||
}
|
||||
|
||||
void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) {
|
||||
|
|
|
@ -28,7 +28,8 @@ class GLRInputLayout;
|
|||
|
||||
enum class GLRRenderCommand : uint8_t {
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
STENCILFUNC,
|
||||
STENCILOP,
|
||||
BLEND,
|
||||
BLENDCOLOR,
|
||||
UNIFORM4I,
|
||||
|
@ -77,13 +78,15 @@ struct GLRRenderData {
|
|||
struct {
|
||||
GLboolean enabled;
|
||||
GLenum func;
|
||||
uint8_t writeMask;
|
||||
uint8_t compareMask;
|
||||
uint8_t ref;
|
||||
uint8_t compareMask;
|
||||
} stencilFunc;
|
||||
struct {
|
||||
GLenum sFail;
|
||||
GLenum zFail;
|
||||
GLenum pass;
|
||||
} stencil;
|
||||
uint8_t writeMask;
|
||||
} stencilOp; // also write mask
|
||||
struct {
|
||||
GLenum mode; // primitive
|
||||
GLint buffer;
|
||||
|
@ -299,6 +302,10 @@ public:
|
|||
|
||||
void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels);
|
||||
|
||||
void Resize(int width, int height) {
|
||||
targetWidth_ = width;
|
||||
targetHeight_ = height;
|
||||
}
|
||||
private:
|
||||
void PerformBindFramebufferAsRenderTarget(const GLRStep &pass);
|
||||
void PerformRenderPass(const GLRStep &pass);
|
||||
|
@ -318,8 +325,10 @@ private:
|
|||
GLuint globalVAO_;
|
||||
|
||||
GLint curFramebuffer_ = 0;
|
||||
int curFBWidth_;
|
||||
int curFBHeight_;
|
||||
int curFBWidth_ = 0;
|
||||
int curFBHeight_ = 0;
|
||||
int targetWidth_ = 0;
|
||||
int targetHeight_ = 0;
|
||||
|
||||
// Readback buffer. Currently we only support synchronous readback, so we only really need one.
|
||||
// We size it generously.
|
||||
|
|
|
@ -456,25 +456,31 @@ public:
|
|||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) {
|
||||
void SetStencilFunc(bool enabled, GLenum func, uint8_t refValue, uint8_t compareMask) {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
|
||||
GLRRenderData data{ GLRRenderCommand::STENCIL };
|
||||
data.stencil.enabled = enabled;
|
||||
data.stencil.func = func;
|
||||
data.stencil.sFail = sFail;
|
||||
data.stencil.zFail = zFail;
|
||||
data.stencil.pass = pass;
|
||||
data.stencil.writeMask = writeMask;
|
||||
data.stencil.compareMask = compareMask;
|
||||
data.stencil.ref = refValue;
|
||||
GLRRenderData data{ GLRRenderCommand::STENCILFUNC };
|
||||
data.stencilFunc.enabled = enabled;
|
||||
data.stencilFunc.func = func;
|
||||
data.stencilFunc.ref = refValue;
|
||||
data.stencilFunc.compareMask = compareMask;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void SetStencilOp(uint8_t writeMask, GLenum sFail, GLenum zFail, GLenum pass) {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
|
||||
GLRRenderData data{ GLRRenderCommand::STENCILOP };
|
||||
data.stencilOp.writeMask = writeMask;
|
||||
data.stencilOp.sFail = sFail;
|
||||
data.stencilOp.zFail = zFail;
|
||||
data.stencilOp.pass = pass;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void SetStencilDisabled() {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
|
||||
GLRRenderData data;
|
||||
data.cmd = GLRRenderCommand::STENCIL;
|
||||
data.stencil.enabled = false;
|
||||
data.cmd = GLRRenderCommand::STENCILFUNC;
|
||||
data.stencilFunc.enabled = false;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
|
@ -546,6 +552,12 @@ public:
|
|||
return curFrame_;
|
||||
}
|
||||
|
||||
void Resize(int width, int height) {
|
||||
targetWidth_ = width;
|
||||
targetHeight_ = height;
|
||||
queueRunner_.Resize(width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
void BeginSubmitFrame(int frame);
|
||||
void EndSubmitFrame(int frame);
|
||||
|
@ -601,6 +613,9 @@ private:
|
|||
bool useThread_ = false;
|
||||
|
||||
int curFrame_ = 0;
|
||||
|
||||
int targetWidth_ = 0;
|
||||
int targetHeight_ = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -633,7 +633,7 @@ public:
|
|||
virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0;
|
||||
|
||||
// Necessary to correctly flip scissor rectangles etc for OpenGL.
|
||||
void SetTargetSize(int w, int h) {
|
||||
virtual void SetTargetSize(int w, int h) {
|
||||
targetWidth_ = w;
|
||||
targetHeight_ = h;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "thin3d/thin3d.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx/gl_debug_log.h"
|
||||
#include "gfx/GLStateCache.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
|
||||
#include "thin3d/GLRenderManager.h"
|
||||
|
@ -207,7 +206,8 @@ public:
|
|||
|
||||
void Apply(GLRenderManager *render) {
|
||||
render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp);
|
||||
render->SetStencil(stencilEnabled, stencilCompareOp, stencilFail, stencilZFail, stencilPass, stencilWriteMask, stencilCompareMask, stencilReference);
|
||||
render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilReference, stencilCompareMask);
|
||||
render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -345,6 +345,11 @@ public:
|
|||
OpenGLContext();
|
||||
virtual ~OpenGLContext();
|
||||
|
||||
void SetTargetSize(int w, int h) override {
|
||||
DrawContext::SetTargetSize(w, h);
|
||||
renderManager_.Resize(w, h);
|
||||
}
|
||||
|
||||
const DeviceCaps &GetDeviceCaps() const override {
|
||||
return caps_;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue