CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/GPU/GLES/StencilBufferGLES.cpp
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include <algorithm>1819#include "Common/GPU/OpenGL/GLFeatures.h"20#include "Common/LogReporting.h"21#include "Core/ConfigValues.h"22#include "GPU/Common/GPUStateUtils.h"23#include "GPU/Common/DrawEngineCommon.h"24#include "GPU/Common/TextureCacheCommon.h"25#include "GPU/GLES/FramebufferManagerGLES.h"26#include "Common/GPU/ShaderWriter.h"2728static const InputDef vs_inputs[] = {29{ "vec2", "a_position", Draw::SEM_POSITION },30};3132struct DepthUB {33float u_depthFactor[4];34float u_depthShift[4];35float u_depthTo8[4];36};3738const UniformDef depthUniforms[] = {39{ "vec4", "u_depthFactor", 0 },40{ "vec4", "u_depthShift", 1},41{ "vec4", "u_depthTo8", 2},42};4344const UniformBufferDesc depthUBDesc{ sizeof(DepthUB), {45{ "u_depthFactor", -1, -1, UniformType::FLOAT4, 0 },46{ "u_depthShift", -1, -1, UniformType::FLOAT4, 16 },47{ "u_depthTo8", -1, -1, UniformType::FLOAT4, 32 },48} };4950static const SamplerDef samplers[] = {51{ 0, "tex" },52};5354static const VaryingDef varyings[] = {55{ "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" },56};5758static const char * const stencil_dl_fs = R"(59#ifdef GL_ES60#ifdef GL_FRAGMENT_PRECISION_HIGH61precision highp float;62#else63precision mediump float;64#endif65#endif66#if __VERSION__ >= 13067#define varying in68#define texture2D texture69#define gl_FragColor fragColor070out vec4 fragColor0;71#endif72varying vec2 v_texcoord;73lowp uniform usampler2D tex;74void main() {75uint stencil = texture2D(tex, v_texcoord).r;76float scaled = float(stencil) / 255.0;77gl_FragColor = vec4(scaled, scaled, scaled, scaled);78}79)";8081static const char * const stencil_vs = R"(82#ifdef GL_ES83precision highp float;84#endif85#if __VERSION__ >= 13086#define attribute in87#define varying out88#endif89attribute vec2 a_position;90varying vec2 v_texcoord;91void main() {92v_texcoord = a_position * 2.0;93gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);94}95)";9697Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag);9899// Well, this is not depth, but it's depth/stencil related.100bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) {101using namespace Draw;102103if (!fbo) {104ERROR_LOG_REPORT_ONCE(vfbfbozero, Log::sceGe, "ReadbackStencilbufferSync: bad fbo");105return false;106}107108const bool useColorPath = gl_extensions.IsGLES;109if (!useColorPath) {110return draw_->CopyFramebufferToMemory(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, ReadbackMode::BLOCK, "ReadbackStencilbufferSync");111}112113// Unsupported below GLES 3.1 or without ARB_stencil_texturing.114// OES_texture_stencil8 is related, but used to specify texture data.115if ((gl_extensions.IsGLES && !gl_extensions.VersionGEThan(3, 1)) && !gl_extensions.ARB_stencil_texturing)116return false;117118// Pixel size always 4 here because we always request RGBA back.119const u32 bufSize = w * h * 4;120if (!convBuf_ || convBufSize_ < bufSize) {121delete[] convBuf_;122convBuf_ = new u8[bufSize];123convBufSize_ = bufSize;124}125126if (!stencilReadbackPipeline_) {127stencilReadbackPipeline_ = CreateReadbackPipeline(draw_, "stencil_dl", &depthUBDesc, stencil_dl_fs, "stencil_dl_fs", stencil_vs, "stencil_vs");128stencilReadbackSampler_ = draw_->CreateSamplerState({});129}130131shaderManager_->DirtyLastShader();132auto *blitFBO = GetTempFBO(TempFBO::Z_COPY, fbo->Width(), fbo->Height());133draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackStencilbufferSync");134Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f };135draw_->SetViewport(viewport);136137draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_STENCIL_BIT, 0);138draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &stencilReadbackSampler_);139140// We must bind the program after starting the render pass.141draw_->SetScissorRect(0, 0, w, h);142draw_->BindPipeline(stencilReadbackPipeline_);143144// Fullscreen triangle coordinates.145static const float positions[6] = {1460.0, 0.0,1471.0, 0.0,1480.0, 1.0,149};150draw_->DrawUP(positions, 3);151152draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, mode, "ReadbackStencilbufferSync");153154textureCache_->ForgetLastTexture();155156// TODO: Use 1/4 width to write all values directly and skip CPU conversion?157uint8_t *dest = pixels;158const u32_le *packed32 = (u32_le *)convBuf_;159for (int yp = 0; yp < h; ++yp) {160for (int xp = 0; xp < w; ++xp) {161dest[xp] = packed32[xp] & 0xFF;162}163dest += pixelsStride;164packed32 += w;165}166167gstate_c.Dirty(DIRTY_ALL_RENDER_STATE);168return true;169}170171172