CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/GPU/GLES/StencilBufferGLES.cpp
Views: 1401
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include <algorithm>
19
20
#include "Common/GPU/OpenGL/GLFeatures.h"
21
#include "Common/LogReporting.h"
22
#include "Core/ConfigValues.h"
23
#include "GPU/Common/GPUStateUtils.h"
24
#include "GPU/Common/DrawEngineCommon.h"
25
#include "GPU/Common/TextureCacheCommon.h"
26
#include "GPU/GLES/FramebufferManagerGLES.h"
27
#include "Common/GPU/ShaderWriter.h"
28
29
static const InputDef vs_inputs[] = {
30
{ "vec2", "a_position", Draw::SEM_POSITION },
31
};
32
33
struct DepthUB {
34
float u_depthFactor[4];
35
float u_depthShift[4];
36
float u_depthTo8[4];
37
};
38
39
const UniformDef depthUniforms[] = {
40
{ "vec4", "u_depthFactor", 0 },
41
{ "vec4", "u_depthShift", 1},
42
{ "vec4", "u_depthTo8", 2},
43
};
44
45
const UniformBufferDesc depthUBDesc{ sizeof(DepthUB), {
46
{ "u_depthFactor", -1, -1, UniformType::FLOAT4, 0 },
47
{ "u_depthShift", -1, -1, UniformType::FLOAT4, 16 },
48
{ "u_depthTo8", -1, -1, UniformType::FLOAT4, 32 },
49
} };
50
51
static const SamplerDef samplers[] = {
52
{ 0, "tex" },
53
};
54
55
static const VaryingDef varyings[] = {
56
{ "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" },
57
};
58
59
static const char * const stencil_dl_fs = R"(
60
#ifdef GL_ES
61
#ifdef GL_FRAGMENT_PRECISION_HIGH
62
precision highp float;
63
#else
64
precision mediump float;
65
#endif
66
#endif
67
#if __VERSION__ >= 130
68
#define varying in
69
#define texture2D texture
70
#define gl_FragColor fragColor0
71
out vec4 fragColor0;
72
#endif
73
varying vec2 v_texcoord;
74
lowp uniform usampler2D tex;
75
void main() {
76
uint stencil = texture2D(tex, v_texcoord).r;
77
float scaled = float(stencil) / 255.0;
78
gl_FragColor = vec4(scaled, scaled, scaled, scaled);
79
}
80
)";
81
82
static const char * const stencil_vs = R"(
83
#ifdef GL_ES
84
precision highp float;
85
#endif
86
#if __VERSION__ >= 130
87
#define attribute in
88
#define varying out
89
#endif
90
attribute vec2 a_position;
91
varying vec2 v_texcoord;
92
void main() {
93
v_texcoord = a_position * 2.0;
94
gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);
95
}
96
)";
97
98
Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag);
99
100
// Well, this is not depth, but it's depth/stencil related.
101
bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) {
102
using namespace Draw;
103
104
if (!fbo) {
105
ERROR_LOG_REPORT_ONCE(vfbfbozero, Log::sceGe, "ReadbackStencilbufferSync: bad fbo");
106
return false;
107
}
108
109
const bool useColorPath = gl_extensions.IsGLES;
110
if (!useColorPath) {
111
return draw_->CopyFramebufferToMemory(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, ReadbackMode::BLOCK, "ReadbackStencilbufferSync");
112
}
113
114
// Unsupported below GLES 3.1 or without ARB_stencil_texturing.
115
// OES_texture_stencil8 is related, but used to specify texture data.
116
if ((gl_extensions.IsGLES && !gl_extensions.VersionGEThan(3, 1)) && !gl_extensions.ARB_stencil_texturing)
117
return false;
118
119
// Pixel size always 4 here because we always request RGBA back.
120
const u32 bufSize = w * h * 4;
121
if (!convBuf_ || convBufSize_ < bufSize) {
122
delete[] convBuf_;
123
convBuf_ = new u8[bufSize];
124
convBufSize_ = bufSize;
125
}
126
127
if (!stencilReadbackPipeline_) {
128
stencilReadbackPipeline_ = CreateReadbackPipeline(draw_, "stencil_dl", &depthUBDesc, stencil_dl_fs, "stencil_dl_fs", stencil_vs, "stencil_vs");
129
stencilReadbackSampler_ = draw_->CreateSamplerState({});
130
}
131
132
shaderManager_->DirtyLastShader();
133
auto *blitFBO = GetTempFBO(TempFBO::Z_COPY, fbo->Width(), fbo->Height());
134
draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackStencilbufferSync");
135
Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f };
136
draw_->SetViewport(viewport);
137
138
draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_STENCIL_BIT, 0);
139
draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &stencilReadbackSampler_);
140
141
// We must bind the program after starting the render pass.
142
draw_->SetScissorRect(0, 0, w, h);
143
draw_->BindPipeline(stencilReadbackPipeline_);
144
145
// Fullscreen triangle coordinates.
146
static const float positions[6] = {
147
0.0, 0.0,
148
1.0, 0.0,
149
0.0, 1.0,
150
};
151
draw_->DrawUP(positions, 3);
152
153
draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, mode, "ReadbackStencilbufferSync");
154
155
textureCache_->ForgetLastTexture();
156
157
// TODO: Use 1/4 width to write all values directly and skip CPU conversion?
158
uint8_t *dest = pixels;
159
const u32_le *packed32 = (u32_le *)convBuf_;
160
for (int yp = 0; yp < h; ++yp) {
161
for (int xp = 0; xp < w; ++xp) {
162
dest[xp] = packed32[xp] & 0xFF;
163
}
164
dest += pixelsStride;
165
packed32 += w;
166
}
167
168
gstate_c.Dirty(DIRTY_ALL_RENDER_STATE);
169
return true;
170
}
171
172