1 #include "ppsspp_config.h"
2 #include <algorithm>
3 
4 #include "Common/GPU/OpenGL/GLCommon.h"
5 #include "Common/GPU/OpenGL/GLDebugLog.h"
6 #include "Common/GPU/OpenGL/GLFeatures.h"
7 #include "Common/GPU/OpenGL/DataFormatGL.h"
8 #include "Common/Math/math_util.h"
9 
10 #include "Common/Log.h"
11 #include "Common/MemoryUtil.h"
12 #include "Common/StringUtils.h"
13 #include "Common/Data/Convert/SmallDataConvert.h"
14 
15 #include "Core/Reporting.h"
16 #include "GLQueueRunner.h"
17 #include "GLRenderManager.h"
18 #include "DataFormatGL.h"
19 
20 static constexpr int TEXCACHE_NAME_CACHE_SIZE = 16;
21 
22 #if PPSSPP_PLATFORM(IOS)
23 extern void bindDefaultFBO();
24 #endif
25 
26 // Workaround for Retroarch. Simply declare
27 //   extern GLuint g_defaultFBO;
28 // and set is as appropriate. Can adjust the variables in ext/native/base/display.h as
29 // appropriate.
30 GLuint g_defaultFBO = 0;
31 
CreateDeviceObjects()32 void GLQueueRunner::CreateDeviceObjects() {
33 	CHECK_GL_ERROR_IF_DEBUG();
34 	if (gl_extensions.EXT_texture_filter_anisotropic) {
35 		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_);
36 	} else {
37 		maxAnisotropyLevel_ = 0.0f;
38 	}
39 
40 	if (gl_extensions.ARB_vertex_array_object) {
41 		glGenVertexArrays(1, &globalVAO_);
42 	}
43 
44 	// An eternal optimist.
45 	sawOutOfMemory_ = false;
46 
47 	// Populate some strings from the GL thread so they can be queried from thin3d.
48 	// TODO: Merge with GLFeatures.cpp/h
49 	auto populate = [&](int name) {
50 		const GLubyte *value = glGetString(name);
51 		if (!value)
52 			glStrings_[name] = "?";
53 		else
54 			glStrings_[name] = (const char *)value;
55 	};
56 	populate(GL_VENDOR);
57 	populate(GL_RENDERER);
58 	populate(GL_VERSION);
59 	populate(GL_SHADING_LANGUAGE_VERSION);
60 	CHECK_GL_ERROR_IF_DEBUG();
61 
62 	useDebugGroups_ = !gl_extensions.IsGLES && gl_extensions.VersionGEThan(4, 3);
63 }
64 
DestroyDeviceObjects()65 void GLQueueRunner::DestroyDeviceObjects() {
66 	CHECK_GL_ERROR_IF_DEBUG();
67 	if (!nameCache_.empty()) {
68 		glDeleteTextures((GLsizei)nameCache_.size(), &nameCache_[0]);
69 		nameCache_.clear();
70 	}
71 	if (gl_extensions.ARB_vertex_array_object) {
72 		glDeleteVertexArrays(1, &globalVAO_);
73 	}
74 	delete[] readbackBuffer_;
75 	readbackBuffer_ = nullptr;
76 	readbackBufferSize_ = 0;
77 	delete[] tempBuffer_;
78 	tempBuffer_ = nullptr;
79 	tempBufferSize_ = 0;
80 	CHECK_GL_ERROR_IF_DEBUG();
81 }
82 
83 template <typename Getiv, typename GetLog>
GetInfoLog(GLuint name,Getiv getiv,GetLog getLog)84 static std::string GetInfoLog(GLuint name, Getiv getiv, GetLog getLog) {
85 	GLint bufLength = 0;
86 	getiv(name, GL_INFO_LOG_LENGTH, &bufLength);
87 	if (bufLength <= 0)
88 		bufLength = 2048;
89 
90 	std::string infoLog;
91 	infoLog.resize(bufLength);
92 	GLsizei len = 0;
93 	getLog(name, (GLsizei)infoLog.size(), &len, &infoLog[0]);
94 	if (len <= 0)
95 		return "(unknown reason)";
96 
97 	infoLog.resize(len);
98 	return infoLog;
99 }
100 
RunInitSteps(const std::vector<GLRInitStep> & steps,bool skipGLCalls)101 void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls) {
102 	if (skipGLCalls) {
103 		// Some bookkeeping still needs to be done.
104 		for (size_t i = 0; i < steps.size(); i++) {
105 			const GLRInitStep &step = steps[i];
106 			switch (step.stepType) {
107 			case GLRInitStepType::BUFFER_SUBDATA:
108 			{
109 				if (step.buffer_subdata.deleteData)
110 					delete[] step.buffer_subdata.data;
111 				break;
112 			}
113 			case GLRInitStepType::TEXTURE_IMAGE:
114 			{
115 				if (step.texture_image.allocType == GLRAllocType::ALIGNED) {
116 					FreeAlignedMemory(step.texture_image.data);
117 				} else if (step.texture_image.allocType == GLRAllocType::NEW) {
118 					delete[] step.texture_image.data;
119 				}
120 				break;
121 			}
122 			case GLRInitStepType::CREATE_PROGRAM:
123 			{
124 				WARN_LOG(G3D, "CREATE_PROGRAM found with skipGLCalls, not good");
125 				break;
126 			}
127 			case GLRInitStepType::CREATE_SHADER:
128 			{
129 				WARN_LOG(G3D, "CREATE_SHADER found with skipGLCalls, not good");
130 				break;
131 			}
132 			default:
133 				break;
134 			}
135 		}
136 		return;
137 	}
138 
139 #if !defined(USING_GLES2)
140 	if (useDebugGroups_)
141 		glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "InitSteps");
142 #endif
143 
144 	CHECK_GL_ERROR_IF_DEBUG();
145 	glActiveTexture(GL_TEXTURE0);
146 	GLuint boundTexture = (GLuint)-1;
147 	bool allocatedTextures = false;
148 
149 	for (size_t i = 0; i < steps.size(); i++) {
150 		const GLRInitStep &step = steps[i];
151 		switch (step.stepType) {
152 		case GLRInitStepType::CREATE_TEXTURE:
153 		{
154 			GLRTexture *tex = step.create_texture.texture;
155 			glGenTextures(1, &tex->texture);
156 			glBindTexture(tex->target, tex->texture);
157 			boundTexture = tex->texture;
158 			CHECK_GL_ERROR_IF_DEBUG();
159 			break;
160 		}
161 		case GLRInitStepType::CREATE_BUFFER:
162 		{
163 			GLRBuffer *buffer = step.create_buffer.buffer;
164 			glGenBuffers(1, &buffer->buffer_);
165 			glBindBuffer(buffer->target_, buffer->buffer_);
166 			glBufferData(buffer->target_, step.create_buffer.size, nullptr, step.create_buffer.usage);
167 			CHECK_GL_ERROR_IF_DEBUG();
168 			break;
169 		}
170 		case GLRInitStepType::BUFFER_SUBDATA:
171 		{
172 			GLRBuffer *buffer = step.buffer_subdata.buffer;
173 			glBindBuffer(buffer->target_, buffer->buffer_);
174 			glBufferSubData(buffer->target_, step.buffer_subdata.offset, step.buffer_subdata.size, step.buffer_subdata.data);
175 			if (step.buffer_subdata.deleteData)
176 				delete[] step.buffer_subdata.data;
177 			CHECK_GL_ERROR_IF_DEBUG();
178 			break;
179 		}
180 		case GLRInitStepType::CREATE_PROGRAM:
181 		{
182 			CHECK_GL_ERROR_IF_DEBUG();
183 			GLRProgram *program = step.create_program.program;
184 			program->program = glCreateProgram();
185 			_assert_msg_(step.create_program.num_shaders > 0, "Can't create a program with zero shaders");
186 			bool anyFailed = false;
187 			for (int j = 0; j < step.create_program.num_shaders; j++) {
188 				_dbg_assert_msg_(step.create_program.shaders[j]->shader, "Can't create a program with a null shader");
189 				anyFailed = anyFailed || step.create_program.shaders[j]->failed;
190 				glAttachShader(program->program, step.create_program.shaders[j]->shader);
191 			}
192 
193 			for (auto iter : program->semantics_) {
194 				glBindAttribLocation(program->program, iter.location, iter.attrib);
195 			}
196 
197 #if !defined(USING_GLES2)
198 			if (step.create_program.support_dual_source) {
199 				// Dual source alpha
200 				glBindFragDataLocationIndexed(program->program, 0, 0, "fragColor0");
201 				glBindFragDataLocationIndexed(program->program, 0, 1, "fragColor1");
202 			} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
203 				glBindFragDataLocation(program->program, 0, "fragColor0");
204 			}
205 #elif !PPSSPP_PLATFORM(IOS)
206 			if (gl_extensions.GLES3 && step.create_program.support_dual_source) {
207 				glBindFragDataLocationIndexedEXT(program->program, 0, 0, "fragColor0");
208 				glBindFragDataLocationIndexedEXT(program->program, 0, 1, "fragColor1");
209 			}
210 #endif
211 			glLinkProgram(program->program);
212 
213 			GLint linkStatus = GL_FALSE;
214 			glGetProgramiv(program->program, GL_LINK_STATUS, &linkStatus);
215 			if (linkStatus != GL_TRUE) {
216 				std::string infoLog = GetInfoLog(program->program, glGetProgramiv, glGetProgramInfoLog);
217 
218 				// TODO: Could be other than vs/fs.  Also, we're assuming order here...
219 				GLRShader *vs = step.create_program.shaders[0];
220 				GLRShader *fs = step.create_program.num_shaders > 1 ? step.create_program.shaders[1] : nullptr;
221 				std::string vsDesc = vs->desc + (vs->failed ? " (failed)" : "");
222 				std::string fsDesc = fs ? (fs->desc + (fs->failed ? " (failed)" : "")) : "(none)";
223 				const char *vsCode = vs->code.c_str();
224 				const char *fsCode = fs ? fs->code.c_str() : "(none)";
225 				if (!anyFailed)
226 					Reporting::ReportMessage("Error in shader program link: info: %s\nfs: %s\n%s\nvs: %s\n%s", infoLog.c_str(), fsDesc.c_str(), fsCode, vsDesc.c_str(), vsCode);
227 
228 				ERROR_LOG(G3D, "Could not link program:\n %s", infoLog.c_str());
229 				ERROR_LOG(G3D, "VS desc:\n%s", vsDesc.c_str());
230 				ERROR_LOG(G3D, "FS desc:\n%s", fsDesc.c_str());
231 				ERROR_LOG(G3D, "VS:\n%s\n", vsCode);
232 				ERROR_LOG(G3D, "FS:\n%s\n", fsCode);
233 
234 #ifdef _WIN32
235 				OutputDebugStringUTF8(infoLog.c_str());
236 				if (vsCode)
237 					OutputDebugStringUTF8(LineNumberString(vsCode).c_str());
238 				if (fsCode)
239 					OutputDebugStringUTF8(LineNumberString(fsCode).c_str());
240 #endif
241 				CHECK_GL_ERROR_IF_DEBUG();
242 				break;
243 			}
244 
245 			glUseProgram(program->program);
246 
247 			// Query all the uniforms.
248 			for (size_t j = 0; j < program->queries_.size(); j++) {
249 				auto &x = program->queries_[j];
250 				_dbg_assert_(x.name);
251 				*x.dest = glGetUniformLocation(program->program, x.name);
252 			}
253 
254 			// Run initializers.
255 			for (size_t j = 0; j < program->initialize_.size(); j++) {
256 				auto &init = program->initialize_[j];
257 				GLint uniform = *init.uniform;
258 				if (uniform != -1) {
259 					switch (init.type) {
260 					case 0:
261 						glUniform1i(uniform, init.value);
262 						break;
263 					}
264 				}
265 			}
266 			CHECK_GL_ERROR_IF_DEBUG();
267 			break;
268 		}
269 		case GLRInitStepType::CREATE_SHADER:
270 		{
271 			CHECK_GL_ERROR_IF_DEBUG();
272 			GLuint shader = glCreateShader(step.create_shader.stage);
273 			step.create_shader.shader->shader = shader;
274 			const char *code = step.create_shader.code;
275 			glShaderSource(shader, 1, &code, nullptr);
276 			glCompileShader(shader);
277 			GLint success = 0;
278 			glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
279 			std::string infoLog = GetInfoLog(shader, glGetShaderiv, glGetShaderInfoLog);
280 			if (!success) {
281 				std::string errorString = StringFromFormat(
282 					"Error in shader compilation for: %s\n"
283 					"Info log: %s\n"
284 					"Shader source:\n%s\n//END\n\n",
285 					step.create_shader.shader->desc.c_str(),
286 					infoLog.c_str(),
287 					LineNumberString(code).c_str());
288 				std::vector<std::string> lines;
289 				SplitString(errorString, '\n', lines);
290 				for (auto &line : lines) {
291 					ERROR_LOG(G3D, "%s", line.c_str());
292 				}
293 				if (errorCallback_) {
294 					std::string desc = StringFromFormat("Shader compilation failed: %s", step.create_shader.stage == GL_VERTEX_SHADER ? "vertex" : "fragment");
295 					errorCallback_(desc.c_str(), errorString.c_str(), errorCallbackUserData_);
296 				}
297 				Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog.c_str(), step.create_shader.shader->desc.c_str(), (const char *)code);
298 #ifdef SHADERLOG
299 				OutputDebugStringUTF8(infoLog.c_str());
300 #endif
301 				step.create_shader.shader->failed = true;
302 				step.create_shader.shader->error = infoLog;  // Hm, we never use this.
303 			}
304 			// Before we throw away the code, attach it to the shader for debugging.
305 			step.create_shader.shader->code = code;
306 			delete[] step.create_shader.code;
307 			step.create_shader.shader->valid = true;
308 			CHECK_GL_ERROR_IF_DEBUG();
309 			break;
310 		}
311 		case GLRInitStepType::CREATE_INPUT_LAYOUT:
312 		{
313 			// GLRInputLayout *layout = step.create_input_layout.inputLayout;
314 			// Nothing to do unless we want to create vertexbuffer objects (GL 4.5)
315 			break;
316 		}
317 		case GLRInitStepType::CREATE_FRAMEBUFFER:
318 		{
319 			CHECK_GL_ERROR_IF_DEBUG();
320 			boundTexture = (GLuint)-1;
321 			InitCreateFramebuffer(step);
322 			allocatedTextures = true;
323 			CHECK_GL_ERROR_IF_DEBUG();
324 			break;
325 		}
326 		case GLRInitStepType::TEXTURE_IMAGE:
327 		{
328 			GLRTexture *tex = step.texture_image.texture;
329 			CHECK_GL_ERROR_IF_DEBUG();
330 			if (boundTexture != tex->texture) {
331 				glBindTexture(tex->target, tex->texture);
332 				boundTexture = tex->texture;
333 			}
334 			if (!step.texture_image.data && step.texture_image.allocType != GLRAllocType::NONE)
335 				Crash();
336 			// For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage.
337 
338 			GLenum internalFormat, format, type;
339 			int alignment;
340 			Thin3DFormatToFormatAndType(step.texture_image.format, internalFormat, format, type, alignment);
341 			glTexImage2D(tex->target, step.texture_image.level, internalFormat, step.texture_image.width, step.texture_image.height, 0, format, type, step.texture_image.data);
342 			allocatedTextures = true;
343 			if (step.texture_image.allocType == GLRAllocType::ALIGNED) {
344 				FreeAlignedMemory(step.texture_image.data);
345 			} else if (step.texture_image.allocType == GLRAllocType::NEW) {
346 				delete[] step.texture_image.data;
347 			}
348 			CHECK_GL_ERROR_IF_DEBUG();
349 			tex->wrapS = GL_CLAMP_TO_EDGE;
350 			tex->wrapT = GL_CLAMP_TO_EDGE;
351 			tex->magFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST;
352 			tex->minFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST;
353 			glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, tex->wrapS);
354 			glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, tex->wrapT);
355 			glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, tex->magFilter);
356 			glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, tex->minFilter);
357 			CHECK_GL_ERROR_IF_DEBUG();
358 			break;
359 		}
360 		case GLRInitStepType::TEXTURE_FINALIZE:
361 		{
362 			CHECK_GL_ERROR_IF_DEBUG();
363 			GLRTexture *tex = step.texture_finalize.texture;
364 			if (boundTexture != tex->texture) {
365 				glBindTexture(tex->target, tex->texture);
366 				boundTexture = tex->texture;
367 			}
368 			if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
369 				glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel);
370 			}
371 			tex->maxLod = (float)step.texture_finalize.maxLevel;
372 			if (step.texture_finalize.genMips) {
373 				glGenerateMipmap(tex->target);
374 			}
375 			CHECK_GL_ERROR_IF_DEBUG();
376 			break;
377 		}
378 		default:
379 			CHECK_GL_ERROR_IF_DEBUG();
380 			Crash();
381 			break;
382 		}
383 	}
384 	CHECK_GL_ERROR_IF_DEBUG();
385 
386 	// TODO: Use GL_KHR_no_error or a debug callback, where supported?
387 	if (false && allocatedTextures) {
388 		// Users may use replacements or scaling, with high render resolutions, and run out of VRAM.
389 		// This detects that, rather than looking like PPSSPP is broken.
390 		// Calling glGetError() isn't great, but at the end of init, only after creating textures, shouldn't be too bad...
391 		GLenum err = glGetError();
392 		if (err == GL_OUT_OF_MEMORY) {
393 			WARN_LOG_REPORT(G3D, "GL ran out of GPU memory; switching to low memory mode");
394 			sawOutOfMemory_ = true;
395 		} else if (err != GL_NO_ERROR) {
396 			// We checked the err anyway, might as well log if there is one.
397 			std::string errorString = GLEnumToString(err);
398 			WARN_LOG(G3D, "Got an error after init: %08x (%s)", err, errorString.c_str());
399 			if (errorCallback_) {
400 				errorCallback_("GL frame init error", errorString.c_str(), errorCallbackUserData_);
401 			}
402 		}
403 	}
404 
405 	glBindBuffer(GL_ARRAY_BUFFER, 0);
406 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
407 
408 #if !defined(USING_GLES2)
409 	if (useDebugGroups_)
410 		glPopDebugGroup();
411 #endif
412 }
413 
InitCreateFramebuffer(const GLRInitStep & step)414 void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
415 	GLRFramebuffer *fbo = step.create_framebuffer.framebuffer;
416 
417 #ifndef USING_GLES2
418 	if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) {
419 		fbo_ext_create(step);
420 	} else if (!gl_extensions.ARB_framebuffer_object && !gl_extensions.IsGLES) {
421 		return;
422 	}
423 	// If GLES2, we have basic FBO support and can just proceed.
424 #endif
425 	CHECK_GL_ERROR_IF_DEBUG();
426 
427 	auto initFBOTexture = [&](GLRTexture &tex, GLint internalFormat, GLenum format, GLenum type, bool linear) {
428 		glGenTextures(1, &tex.texture);
429 		tex.target = GL_TEXTURE_2D;
430 		tex.maxLod = 0.0f;
431 
432 		// Create the surfaces.
433 		glBindTexture(GL_TEXTURE_2D, tex.texture);
434 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, fbo->width, fbo->height, 0, format, type, nullptr);
435 
436 		tex.wrapS = GL_CLAMP_TO_EDGE;
437 		tex.wrapT = GL_CLAMP_TO_EDGE;
438 		tex.magFilter = linear ? GL_LINEAR : GL_NEAREST;
439 		tex.minFilter = linear ? GL_LINEAR : GL_NEAREST;
440 
441 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex.wrapS);
442 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex.wrapT);
443 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex.magFilter);
444 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex.minFilter);
445 		if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
446 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
447 		}
448 	};
449 
450 	// Color texture is same everywhere
451 	glGenFramebuffers(1, &fbo->handle);
452 	initFBOTexture(fbo->color_texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true);
453 
454 retry_depth:
455 	if (!fbo->z_stencil_) {
456 		INFO_LOG(G3D, "Creating %d x %d FBO using no depth", fbo->width, fbo->height);
457 
458 		fbo->z_stencil_buffer = 0;
459 		fbo->stencil_buffer = 0;
460 		fbo->z_buffer = 0;
461 
462 		// Bind it all together
463 		glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
464 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
465 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
466 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
467 	} else if (gl_extensions.IsGLES) {
468 		if (gl_extensions.OES_packed_depth_stencil && (gl_extensions.OES_depth_texture || gl_extensions.GLES3)) {
469 			INFO_LOG(G3D, "Creating %d x %d FBO using DEPTH24_STENCIL8 texture", fbo->width, fbo->height);
470 			fbo->z_stencil_buffer = 0;
471 			fbo->stencil_buffer = 0;
472 			fbo->z_buffer = 0;
473 
474 			if (gl_extensions.GLES3) {
475 				initFBOTexture(fbo->z_stencil_texture, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
476 			} else {
477 				initFBOTexture(fbo->z_stencil_texture, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
478 			}
479 
480 			// Bind it all together
481 			glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
482 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
483 			if (gl_extensions.GLES3) {
484 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
485 			} else {
486 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
487 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
488 			}
489 		} else if (gl_extensions.OES_packed_depth_stencil) {
490 			INFO_LOG(G3D, "Creating %d x %d FBO using DEPTH24_STENCIL8", fbo->width, fbo->height);
491 			// Standard method
492 			fbo->stencil_buffer = 0;
493 			fbo->z_buffer = 0;
494 			// 24-bit Z, 8-bit stencil combined
495 			glGenRenderbuffers(1, &fbo->z_stencil_buffer);
496 			glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer);
497 			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbo->width, fbo->height);
498 
499 			// Bind it all together
500 			glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
501 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
502 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
503 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
504 		} else {
505 			INFO_LOG(G3D, "Creating %d x %d FBO using separate stencil", fbo->width, fbo->height);
506 			// TEGRA
507 			fbo->z_stencil_buffer = 0;
508 			// 16/24-bit Z, separate 8-bit stencil
509 			glGenRenderbuffers(1, &fbo->z_buffer);
510 			glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer);
511 			// Don't forget to make sure fbo_standard_z_depth() matches.
512 			glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, fbo->width, fbo->height);
513 
514 			// 8-bit stencil buffer
515 			glGenRenderbuffers(1, &fbo->stencil_buffer);
516 			glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer);
517 			glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbo->width, fbo->height);
518 
519 			// Bind it all together
520 			glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
521 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
522 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer);
523 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer);
524 		}
525 	} else if (gl_extensions.VersionGEThan(3, 0)) {
526 		INFO_LOG(G3D, "Creating %d x %d FBO using DEPTH24_STENCIL8 texture", fbo->width, fbo->height);
527 		fbo->z_stencil_buffer = 0;
528 		fbo->stencil_buffer = 0;
529 		fbo->z_buffer = 0;
530 
531 		initFBOTexture(fbo->z_stencil_texture, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
532 
533 		// Bind it all together
534 		glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
535 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
536 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
537 	} else {
538 		fbo->stencil_buffer = 0;
539 		fbo->z_buffer = 0;
540 		// 24-bit Z, 8-bit stencil
541 		glGenRenderbuffers(1, &fbo->z_stencil_buffer);
542 		glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer);
543 		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbo->width, fbo->height);
544 
545 		// Bind it all together
546 		glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
547 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
548 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
549 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
550 	}
551 
552 	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
553 	if (status != GL_FRAMEBUFFER_COMPLETE && !fbo->z_buffer) {
554 		CHECK_GL_ERROR_IF_DEBUG();
555 		// Uh oh, maybe we need a z/stencil.  Platforms sometimes, right?
556 		fbo->z_stencil_ = true;
557 		goto retry_depth;
558 	}
559 
560 	switch (status) {
561 	case GL_FRAMEBUFFER_COMPLETE:
562 		// INFO_LOG(G3D, "Framebuffer verified complete.");
563 		break;
564 	case GL_FRAMEBUFFER_UNSUPPORTED:
565 		ERROR_LOG(G3D, "GL_FRAMEBUFFER_UNSUPPORTED");
566 		break;
567 	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
568 		ERROR_LOG(G3D, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
569 		break;
570 	default:
571 		_assert_msg_(false, "Other framebuffer error: %d", status);
572 		break;
573 	}
574 
575 	// Unbind state we don't need
576 	glBindRenderbuffer(GL_RENDERBUFFER, 0);
577 	glBindTexture(GL_TEXTURE_2D, 0);
578 	CHECK_GL_ERROR_IF_DEBUG();
579 
580 	currentDrawHandle_ = fbo->handle;
581 	currentReadHandle_ = fbo->handle;
582 }
583 
RunSteps(const std::vector<GLRStep * > & steps,bool skipGLCalls)584 void GLQueueRunner::RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls) {
585 	if (skipGLCalls) {
586 		// Dry run
587 		for (size_t i = 0; i < steps.size(); i++) {
588 			const GLRStep &step = *steps[i];
589 			switch (step.stepType) {
590 			case GLRStepType::RENDER:
591 				for (const auto &c : step.commands) {
592 					switch (c.cmd) {
593 					case GLRRenderCommand::TEXTURE_SUBIMAGE:
594 						if (c.texture_subimage.data) {
595 							if (c.texture_subimage.allocType == GLRAllocType::ALIGNED) {
596 								FreeAlignedMemory(c.texture_subimage.data);
597 							} else if (c.texture_subimage.allocType == GLRAllocType::NEW) {
598 								delete[] c.texture_subimage.data;
599 							}
600 						}
601 						break;
602 					default:
603 						break;
604 					}
605 				}
606 				break;
607 			default:
608 				break;
609 			}
610 			delete steps[i];
611 		}
612 		return;
613 	}
614 
615 	size_t totalRenderCount = 0;
616 	for (auto &step : steps) {
617 		if (step->stepType == GLRStepType::RENDER) {
618 			// Skip empty render steps.
619 			if (step->commands.empty()) {
620 				step->stepType = GLRStepType::RENDER_SKIP;
621 				continue;
622 			}
623 			totalRenderCount++;
624 		}
625 	}
626 
627 	auto ignoresContents = [](GLRRenderPassAction act) {
628 		return act == GLRRenderPassAction::CLEAR || act == GLRRenderPassAction::DONT_CARE;
629 	};
630 	int invalidateAllMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
631 
632 	/*
633 	for (int j = 0; j < (int)steps.size() - 1; ++j) {
634 		GLRStep &primaryStep = *steps[j];
635 		if (primaryStep.stepType == GLRStepType::RENDER) {
636 			const GLRFramebuffer *fb = primaryStep.render.framebuffer;
637 
638 			// Let's see if we can invalidate it...
639 			int invalidateMask = 0;
640 			for (int i = j + 1; i < (int)steps.size(); ++i) {
641 				const GLRStep &secondaryStep = *steps[i];
642 				if (secondaryStep.stepType == GLRStepType::RENDER && secondaryStep.render.framebuffer == fb) {
643 					if (ignoresContents(secondaryStep.render.color))
644 						invalidateMask |= GL_COLOR_BUFFER_BIT;
645 					if (ignoresContents(secondaryStep.render.depth))
646 						invalidateMask |= GL_DEPTH_BUFFER_BIT;
647 					if (ignoresContents(secondaryStep.render.stencil))
648 						invalidateMask |= GL_STENCIL_BUFFER_BIT;
649 
650 					if (invalidateMask == invalidateAllMask)
651 						break;
652 				} else if (secondaryStep.dependencies.contains(fb)) {
653 					// Can't do it, this step may depend on fb's data.
654 					break;
655 				}
656 			}
657 
658 			if (invalidateMask) {
659 				GLRRenderData data{ GLRRenderCommand::INVALIDATE };
660 				data.clear.clearMask = invalidateMask;
661 				primaryStep.commands.push_back(data);
662 			}
663 		}
664 	}*/
665 
666 	CHECK_GL_ERROR_IF_DEBUG();
667 	size_t renderCount = 0;
668 	for (size_t i = 0; i < steps.size(); i++) {
669 		const GLRStep &step = *steps[i];
670 
671 #if !defined(USING_GLES2)
672 		if (useDebugGroups_)
673 			glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, (GLuint)i + 10000, -1, step.tag);
674 #endif
675 
676 		switch (step.stepType) {
677 		case GLRStepType::RENDER:
678 			renderCount++;
679 			PerformRenderPass(step, renderCount == 1, renderCount == totalRenderCount);
680 			break;
681 		case GLRStepType::COPY:
682 			PerformCopy(step);
683 			break;
684 		case GLRStepType::BLIT:
685 			PerformBlit(step);
686 			break;
687 		case GLRStepType::READBACK:
688 			PerformReadback(step);
689 			break;
690 		case GLRStepType::READBACK_IMAGE:
691 			PerformReadbackImage(step);
692 			break;
693 		case GLRStepType::RENDER_SKIP:
694 			break;
695 		default:
696 			Crash();
697 			break;
698 		}
699 
700 #if !defined(USING_GLES2)
701 		if (useDebugGroups_)
702 			glPopDebugGroup();
703 #endif
704 
705 		delete steps[i];
706 	}
707 	CHECK_GL_ERROR_IF_DEBUG();
708 }
709 
LogSteps(const std::vector<GLRStep * > & steps)710 void GLQueueRunner::LogSteps(const std::vector<GLRStep *> &steps) {
711 
712 }
713 
714 
PerformBlit(const GLRStep & step)715 void GLQueueRunner::PerformBlit(const GLRStep &step) {
716 	CHECK_GL_ERROR_IF_DEBUG();
717 	// Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing
718 	// in ES 2.0 that actually separate them anyway of course, so doesn't matter.
719 	fbo_bind_fb_target(false, step.blit.dst->handle);
720 	fbo_bind_fb_target(true, step.blit.src->handle);
721 
722 	int srcX1 = step.blit.srcRect.x;
723 	int srcY1 = step.blit.srcRect.y;
724 	int srcX2 = step.blit.srcRect.x + step.blit.srcRect.w;
725 	int srcY2 = step.blit.srcRect.y + step.blit.srcRect.h;
726 	int dstX1 = step.blit.dstRect.x;
727 	int dstY1 = step.blit.dstRect.y;
728 	int dstX2 = step.blit.dstRect.x + step.blit.dstRect.w;
729 	int dstY2 = step.blit.dstRect.y + step.blit.dstRect.h;
730 
731 	if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) {
732 		glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, step.blit.aspectMask, step.blit.filter ? GL_LINEAR : GL_NEAREST);
733 		CHECK_GL_ERROR_IF_DEBUG();
734 #if defined(USING_GLES2) && defined(__ANDROID__)  // We only support this extension on Android, it's not even available on PC.
735 	} else if (gl_extensions.NV_framebuffer_blit) {
736 		glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, step.blit.aspectMask, step.blit.filter ? GL_LINEAR : GL_NEAREST);
737 		CHECK_GL_ERROR_IF_DEBUG();
738 #endif // defined(USING_GLES2) && defined(__ANDROID__)
739 	} else {
740 		ERROR_LOG(G3D, "GLQueueRunner: Tried to blit without the capability");
741 	}
742 }
743 
PerformRenderPass(const GLRStep & step,bool first,bool last)744 void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last) {
745 	CHECK_GL_ERROR_IF_DEBUG();
746 
747 	PerformBindFramebufferAsRenderTarget(step);
748 
749 	if (first) {
750 		glDisable(GL_DEPTH_TEST);
751 		glDisable(GL_STENCIL_TEST);
752 		glDisable(GL_BLEND);
753 		glDisable(GL_CULL_FACE);
754 		glDisable(GL_DITHER);
755 		glEnable(GL_SCISSOR_TEST);
756 #ifndef USING_GLES2
757 		if (!gl_extensions.IsGLES) {
758 			glDisable(GL_COLOR_LOGIC_OP);
759 		}
760 #endif
761 	}
762 
763 	/*
764 #ifndef USING_GLES2
765 	if (g_Config.iInternalResolution == 0) {
766 		glLineWidth(std::max(1, (int)(renderWidth_ / 480)));
767 		glPointSize(std::max(1.0f, (float)(renderWidth_ / 480.f)));
768 	} else {
769 		glLineWidth(g_Config.iInternalResolution);
770 		glPointSize((float)g_Config.iInternalResolution);
771 	}
772 #endif
773 	*/
774 
775 	if (first && gl_extensions.ARB_vertex_array_object) {
776 		glBindVertexArray(globalVAO_);
777 	}
778 
779 	GLRProgram *curProgram = nullptr;
780 	int activeSlot = 0;
781 	if (first)
782 		glActiveTexture(GL_TEXTURE0 + activeSlot);
783 
784 	// State filtering tracking.
785 	int attrMask = 0;
786 	int colorMask = -1;
787 	int depthMask = -1;
788 	int depthFunc = -1;
789 	GLuint curArrayBuffer = (GLuint)0;
790 	GLuint curElemArrayBuffer = (GLuint)0;
791 	bool depthEnabled = false;
792 	bool stencilEnabled = false;
793 	bool blendEnabled = false;
794 	bool cullEnabled = false;
795 	bool ditherEnabled = false;
796 	bool depthClampEnabled = false;
797 #ifndef USING_GLES2
798 	int logicOp = -1;
799 	bool logicEnabled = false;
800 #endif
801 	GLuint blendEqColor = (GLuint)-1;
802 	GLuint blendEqAlpha = (GLuint)-1;
803 
804 	GLRTexture *curTex[MAX_GL_TEXTURE_SLOTS]{};
805 
806 	CHECK_GL_ERROR_IF_DEBUG();
807 	auto &commands = step.commands;
808 	for (const auto &c : commands) {
809 		switch (c.cmd) {
810 		case GLRRenderCommand::DEPTH:
811 			if (c.depth.enabled) {
812 				if (!depthEnabled) {
813 					glEnable(GL_DEPTH_TEST);
814 					depthEnabled = true;
815 				}
816 				if (c.depth.write != depthMask) {
817 					glDepthMask(c.depth.write);
818 					depthMask = c.depth.write;
819 				}
820 				if (c.depth.func != depthFunc) {
821 					glDepthFunc(c.depth.func);
822 					depthFunc = c.depth.func;
823 				}
824 			} else if (!c.depth.enabled && depthEnabled) {
825 				glDisable(GL_DEPTH_TEST);
826 				depthEnabled = false;
827 			}
828 			break;
829 		case GLRRenderCommand::STENCILFUNC:
830 			if (c.stencilFunc.enabled) {
831 				if (!stencilEnabled) {
832 					glEnable(GL_STENCIL_TEST);
833 					stencilEnabled = true;
834 				}
835 				glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask);
836 			} else if (stencilEnabled) {
837 				glDisable(GL_STENCIL_TEST);
838 				stencilEnabled = false;
839 			}
840 			CHECK_GL_ERROR_IF_DEBUG();
841 			break;
842 		case GLRRenderCommand::STENCILOP:
843 			glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass);
844 			glStencilMask(c.stencilOp.writeMask);
845 			break;
846 		case GLRRenderCommand::BLEND:
847 			if (c.blend.enabled) {
848 				if (!blendEnabled) {
849 					glEnable(GL_BLEND);
850 					blendEnabled = true;
851 				}
852 				if (blendEqColor != c.blend.funcColor || blendEqAlpha != c.blend.funcAlpha) {
853 					glBlendEquationSeparate(c.blend.funcColor, c.blend.funcAlpha);
854 					blendEqColor = c.blend.funcColor;
855 					blendEqAlpha = c.blend.funcAlpha;
856 				}
857 				glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha);
858 			} else if (!c.blend.enabled && blendEnabled) {
859 				glDisable(GL_BLEND);
860 				blendEnabled = false;
861 			}
862 			if (c.blend.mask != colorMask) {
863 				glColorMask(c.blend.mask & 1, (c.blend.mask >> 1) & 1, (c.blend.mask >> 2) & 1, (c.blend.mask >> 3) & 1);
864 				colorMask = c.blend.mask;
865 			}
866 			CHECK_GL_ERROR_IF_DEBUG();
867 			break;
868 		case GLRRenderCommand::LOGICOP:
869 #ifndef USING_GLES2
870 			if (c.logic.enabled) {
871 				if (!logicEnabled) {
872 					glEnable(GL_COLOR_LOGIC_OP);
873 					logicEnabled = true;
874 				}
875 				if (logicOp != c.logic.logicOp) {
876 					glLogicOp(c.logic.logicOp);
877 				}
878 			} else if (!c.logic.enabled && logicEnabled) {
879 				glDisable(GL_COLOR_LOGIC_OP);
880 				logicEnabled = false;
881 			}
882 #endif
883 			CHECK_GL_ERROR_IF_DEBUG();
884 			break;
885 		case GLRRenderCommand::CLEAR:
886 			// Scissor test is on, and should be on after leaving this case. If we disable it,
887 			// we re-enable it at the end.
888 			if (c.clear.scissorW == 0) {
889 				glDisable(GL_SCISSOR_TEST);
890 			} else {
891 				glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH);
892 			}
893 			if (c.clear.colorMask != colorMask) {
894 				glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1);
895 			}
896 			if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) {
897 				float color[4];
898 				Uint8x4ToFloat4(color, c.clear.clearColor);
899 				glClearColor(color[0], color[1], color[2], color[3]);
900 			}
901 			if (c.clear.clearMask & GL_DEPTH_BUFFER_BIT) {
902 #if defined(USING_GLES2)
903 				glClearDepthf(c.clear.clearZ);
904 #else
905 				if (gl_extensions.IsGLES) {
906 					glClearDepthf(c.clear.clearZ);
907 				} else {
908 					glClearDepth(c.clear.clearZ);
909 				}
910 #endif
911 			}
912 			if (c.clear.clearMask & GL_STENCIL_BUFFER_BIT) {
913 				glClearStencil(c.clear.clearStencil);
914 			}
915 			glClear(c.clear.clearMask);
916 			// Restore the color mask if it was different.
917 			if (c.clear.colorMask != colorMask) {
918 				glColorMask(colorMask & 1, (colorMask >> 1) & 1, (colorMask >> 2) & 1, (colorMask >> 3) & 1);
919 			}
920 			if (c.clear.scissorW == 0) {
921 				glEnable(GL_SCISSOR_TEST);
922 			}
923 			CHECK_GL_ERROR_IF_DEBUG();
924 			break;
925 		case GLRRenderCommand::INVALIDATE:
926 		{
927 			GLenum attachments[3];
928 			int count = 0;
929 			bool isFBO = step.render.framebuffer != nullptr;
930 			bool hasDepth = isFBO ? step.render.framebuffer->z_stencil_ : false;
931 			if (c.clear.clearMask & GL_COLOR_BUFFER_BIT)
932 				attachments[count++] = isFBO ? GL_COLOR_ATTACHMENT0 : GL_COLOR;
933 			if (hasDepth && (c.clear.clearMask & GL_DEPTH_BUFFER_BIT))
934 				attachments[count++] = isFBO ? GL_DEPTH_ATTACHMENT : GL_DEPTH;
935 			if (hasDepth && (c.clear.clearMask & GL_STENCIL_BUFFER_BIT))
936 				attachments[count++] = isFBO ? GL_STENCIL_ATTACHMENT : GL_STENCIL;
937 			if (glInvalidateFramebuffer != nullptr && count != 0)
938 				glInvalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
939 			CHECK_GL_ERROR_IF_DEBUG();
940 			break;
941 		}
942 		case GLRRenderCommand::BLENDCOLOR:
943 			glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]);
944 			break;
945 		case GLRRenderCommand::VIEWPORT:
946 		{
947 			float y = c.viewport.vp.y;
948 			if (!curFB_)
949 				y = curFBHeight_ - y - c.viewport.vp.h;
950 
951 			// TODO: Support FP viewports through glViewportArrays
952 			glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h);
953 #if !defined(USING_GLES2)
954 			if (gl_extensions.IsGLES) {
955 				glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ);
956 			} else {
957 				glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ);
958 			}
959 #else
960 			glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ);
961 #endif
962 			CHECK_GL_ERROR_IF_DEBUG();
963 			break;
964 		}
965 		case GLRRenderCommand::SCISSOR:
966 		{
967 			int y = c.scissor.rc.y;
968 			if (!curFB_)
969 				y = curFBHeight_ - y - c.scissor.rc.h;
970 			glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h);
971 			CHECK_GL_ERROR_IF_DEBUG();
972 			break;
973 		}
974 		case GLRRenderCommand::UNIFORM4F:
975 		{
976 			int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
977 			if (c.uniform4.name) {
978 				loc = curProgram->GetUniformLoc(c.uniform4.name);
979 			}
980 			if (loc >= 0) {
981 				switch (c.uniform4.count) {
982 				case 1:
983 					glUniform1f(loc, c.uniform4.v[0]);
984 					break;
985 				case 2:
986 					glUniform2fv(loc, 1, c.uniform4.v);
987 					break;
988 				case 3:
989 					glUniform3fv(loc, 1, c.uniform4.v);
990 					break;
991 				case 4:
992 					glUniform4fv(loc, 1, c.uniform4.v);
993 					break;
994 				}
995 			}
996 			CHECK_GL_ERROR_IF_DEBUG();
997 			break;
998 		}
999 		case GLRRenderCommand::UNIFORM4UI:
1000 		{
1001 			_dbg_assert_(curProgram);
1002 			int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
1003 			if (c.uniform4.name) {
1004 				loc = curProgram->GetUniformLoc(c.uniform4.name);
1005 			}
1006 			if (loc >= 0) {
1007 				switch (c.uniform4.count) {
1008 				case 1:
1009 					glUniform1uiv(loc, 1, (GLuint *)&c.uniform4.v[0]);
1010 					break;
1011 				case 2:
1012 					glUniform2uiv(loc, 1, (GLuint *)c.uniform4.v);
1013 					break;
1014 				case 3:
1015 					glUniform3uiv(loc, 1, (GLuint *)c.uniform4.v);
1016 					break;
1017 				case 4:
1018 					glUniform4uiv(loc, 1, (GLuint *)c.uniform4.v);
1019 					break;
1020 				}
1021 			}
1022 			CHECK_GL_ERROR_IF_DEBUG();
1023 			break;
1024 		}
1025 		case GLRRenderCommand::UNIFORM4I:
1026 		{
1027 			_dbg_assert_(curProgram);
1028 			int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
1029 			if (c.uniform4.name) {
1030 				loc = curProgram->GetUniformLoc(c.uniform4.name);
1031 			}
1032 			if (loc >= 0) {
1033 				switch (c.uniform4.count) {
1034 				case 1:
1035 					glUniform1iv(loc, 1, (GLint *)&c.uniform4.v[0]);
1036 					break;
1037 				case 2:
1038 					glUniform2iv(loc, 1, (GLint *)c.uniform4.v);
1039 					break;
1040 				case 3:
1041 					glUniform3iv(loc, 1, (GLint *)c.uniform4.v);
1042 					break;
1043 				case 4:
1044 					glUniform4iv(loc, 1, (GLint *)c.uniform4.v);
1045 					break;
1046 				}
1047 			}
1048 			CHECK_GL_ERROR_IF_DEBUG();
1049 			break;
1050 		}
1051 		case GLRRenderCommand::UNIFORMMATRIX:
1052 		{
1053 			_dbg_assert_(curProgram);
1054 			int loc = c.uniformMatrix4.loc ? *c.uniformMatrix4.loc : -1;
1055 			if (c.uniformMatrix4.name) {
1056 				loc = curProgram->GetUniformLoc(c.uniformMatrix4.name);
1057 			}
1058 			if (loc >= 0) {
1059 				glUniformMatrix4fv(loc, 1, false, c.uniformMatrix4.m);
1060 			}
1061 			CHECK_GL_ERROR_IF_DEBUG();
1062 			break;
1063 		}
1064 		case GLRRenderCommand::BINDTEXTURE:
1065 		{
1066 			GLint slot = c.texture.slot;
1067 			if (slot != activeSlot) {
1068 				glActiveTexture(GL_TEXTURE0 + slot);
1069 				activeSlot = slot;
1070 			}
1071 			if (c.texture.texture) {
1072 				if (curTex[slot] != c.texture.texture) {
1073 					glBindTexture(c.texture.texture->target, c.texture.texture->texture);
1074 					curTex[slot] = c.texture.texture;
1075 				}
1076 			} else {
1077 				glBindTexture(GL_TEXTURE_2D, 0);  // Which target? Well we only use this one anyway...
1078 				curTex[slot] = nullptr;
1079 			}
1080 			CHECK_GL_ERROR_IF_DEBUG();
1081 			break;
1082 		}
1083 		case GLRRenderCommand::BIND_FB_TEXTURE:
1084 		{
1085 			GLint slot = c.bind_fb_texture.slot;
1086 			if (slot != activeSlot) {
1087 				glActiveTexture(GL_TEXTURE0 + slot);
1088 				activeSlot = slot;
1089 			}
1090 			if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) {
1091 				if (curTex[slot] != &c.bind_fb_texture.framebuffer->color_texture)
1092 					glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture.texture);
1093 				curTex[slot] = &c.bind_fb_texture.framebuffer->color_texture;
1094 			} else if (c.bind_fb_texture.aspect == GL_DEPTH_BUFFER_BIT) {
1095 				if (curTex[slot] != &c.bind_fb_texture.framebuffer->z_stencil_texture)
1096 					glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->z_stencil_texture.texture);
1097 				curTex[slot] = &c.bind_fb_texture.framebuffer->z_stencil_texture;
1098 			} else {
1099 				// TODO: Stencil texturing?
1100 				curTex[slot] = nullptr;
1101 			}
1102 			CHECK_GL_ERROR_IF_DEBUG();
1103 			break;
1104 		}
1105 		case GLRRenderCommand::BINDPROGRAM:
1106 		{
1107 			if (curProgram != c.program.program) {
1108 				glUseProgram(c.program.program->program);
1109 				curProgram = c.program.program;
1110 			}
1111 			CHECK_GL_ERROR_IF_DEBUG();
1112 			break;
1113 		}
1114 		case GLRRenderCommand::BIND_VERTEX_BUFFER:
1115 		{
1116 			// TODO: Add fast path for glBindVertexBuffer
1117 			GLRInputLayout *layout = c.bindVertexBuffer.inputLayout;
1118 			GLuint buf = c.bindVertexBuffer.buffer ? c.bindVertexBuffer.buffer->buffer_ : 0;
1119 			_dbg_assert_(!c.bindVertexBuffer.buffer->Mapped());
1120 			if (buf != curArrayBuffer) {
1121 				glBindBuffer(GL_ARRAY_BUFFER, buf);
1122 				curArrayBuffer = buf;
1123 			}
1124 			int enable = layout->semanticsMask_ & ~attrMask;
1125 			int disable = (~layout->semanticsMask_) & attrMask;
1126 			for (int i = 0; i < 7; i++) {  // SEM_MAX
1127 				if (enable & (1 << i)) {
1128 					glEnableVertexAttribArray(i);
1129 				}
1130 				if (disable & (1 << i)) {
1131 					glDisableVertexAttribArray(i);
1132 				}
1133 			}
1134 			attrMask = layout->semanticsMask_;
1135 			for (size_t i = 0; i < layout->entries.size(); i++) {
1136 				auto &entry = layout->entries[i];
1137 				glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset));
1138 			}
1139 			CHECK_GL_ERROR_IF_DEBUG();
1140 			break;
1141 		}
1142 		case GLRRenderCommand::BIND_BUFFER:
1143 		{
1144 			if (c.bind_buffer.target == GL_ARRAY_BUFFER) {
1145 				Crash();
1146 			} else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) {
1147 				GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0;
1148 				_dbg_assert_(!c.bind_buffer.buffer->Mapped());
1149 				if (buf != curElemArrayBuffer) {
1150 					glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
1151 					curElemArrayBuffer = buf;
1152 				}
1153 			} else {
1154 				GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0;
1155 				_dbg_assert_(!c.bind_buffer.buffer->Mapped());
1156 				glBindBuffer(c.bind_buffer.target, buf);
1157 			}
1158 			CHECK_GL_ERROR_IF_DEBUG();
1159 			break;
1160 		}
1161 		case GLRRenderCommand::GENMIPS:
1162 			// TODO: Should we include the texture handle in the command?
1163 			// Also, should this not be an init command?
1164 			glGenerateMipmap(GL_TEXTURE_2D);
1165 			break;
1166 		case GLRRenderCommand::DRAW:
1167 			glDrawArrays(c.draw.mode, c.draw.first, c.draw.count);
1168 			break;
1169 		case GLRRenderCommand::DRAW_INDEXED:
1170 			if (c.drawIndexed.instances == 1) {
1171 				glDrawElements(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices);
1172 			} else {
1173 				glDrawElementsInstanced(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices, c.drawIndexed.instances);
1174 			}
1175 			CHECK_GL_ERROR_IF_DEBUG();
1176 			break;
1177 		case GLRRenderCommand::TEXTURESAMPLER:
1178 		{
1179 			CHECK_GL_ERROR_IF_DEBUG();
1180 			GLint slot = c.textureSampler.slot;
1181 			if (slot != activeSlot) {
1182 				glActiveTexture(GL_TEXTURE0 + slot);
1183 				activeSlot = slot;
1184 			}
1185 			GLRTexture *tex = curTex[slot];
1186 			if (!tex) {
1187 				break;
1188 			}
1189 			CHECK_GL_ERROR_IF_DEBUG();
1190 			if (tex->canWrap) {
1191 				if (tex->wrapS != c.textureSampler.wrapS) {
1192 					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
1193 					tex->wrapS = c.textureSampler.wrapS;
1194 				}
1195 				if (tex->wrapT != c.textureSampler.wrapT) {
1196 					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
1197 					tex->wrapT = c.textureSampler.wrapT;
1198 				}
1199 			}
1200 			CHECK_GL_ERROR_IF_DEBUG();
1201 			if (tex->magFilter != c.textureSampler.magFilter) {
1202 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
1203 				tex->magFilter = c.textureSampler.magFilter;
1204 			}
1205 			CHECK_GL_ERROR_IF_DEBUG();
1206 			if (tex->minFilter != c.textureSampler.minFilter) {
1207 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
1208 				tex->minFilter = c.textureSampler.minFilter;
1209 			}
1210 			CHECK_GL_ERROR_IF_DEBUG();
1211 			if (tex->anisotropy != c.textureSampler.anisotropy) {
1212 				if (c.textureSampler.anisotropy != 0.0f) {
1213 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
1214 				}
1215 				tex->anisotropy = c.textureSampler.anisotropy;
1216 			}
1217 			CHECK_GL_ERROR_IF_DEBUG();
1218 			break;
1219 		}
1220 		case GLRRenderCommand::TEXTURELOD:
1221 		{
1222 			GLint slot = c.textureSampler.slot;
1223 			if (slot != activeSlot) {
1224 				glActiveTexture(GL_TEXTURE0 + slot);
1225 				activeSlot = slot;
1226 			}
1227 			GLRTexture *tex = curTex[slot];
1228 			if (!tex) {
1229 				break;
1230 			}
1231 #ifndef USING_GLES2
1232 			if (tex->lodBias != c.textureLod.lodBias && !gl_extensions.IsGLES) {
1233 				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
1234 				tex->lodBias = c.textureLod.lodBias;
1235 			}
1236 #endif
1237 			if (tex->minLod != c.textureLod.minLod) {
1238 				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
1239 				tex->minLod = c.textureLod.minLod;
1240 			}
1241 			if (tex->maxLod != c.textureLod.maxLod) {
1242 				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
1243 				tex->maxLod = c.textureLod.maxLod;
1244 			}
1245 			break;
1246 		}
1247 		case GLRRenderCommand::TEXTURE_SUBIMAGE:
1248 		{
1249 			GLRTexture *tex = c.texture_subimage.texture;
1250 			// TODO: Need bind?
1251 			if (!c.texture_subimage.data)
1252 				Crash();
1253 			// For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage.
1254 			GLuint internalFormat, format, type;
1255 			int alignment;
1256 			Thin3DFormatToFormatAndType(c.texture_subimage.format, internalFormat, format, type, alignment);
1257 			glTexSubImage2D(tex->target, c.texture_subimage.level, c.texture_subimage.x, c.texture_subimage.y, c.texture_subimage.width, c.texture_subimage.height, format, type, c.texture_subimage.data);
1258 			if (c.texture_subimage.allocType == GLRAllocType::ALIGNED) {
1259 				FreeAlignedMemory(c.texture_subimage.data);
1260 			} else if (c.texture_subimage.allocType == GLRAllocType::NEW) {
1261 				delete[] c.texture_subimage.data;
1262 			}
1263 			CHECK_GL_ERROR_IF_DEBUG();
1264 			break;
1265 		}
1266 		case GLRRenderCommand::RASTER:
1267 			if (c.raster.cullEnable) {
1268 				if (!cullEnabled) {
1269 					glEnable(GL_CULL_FACE);
1270 					cullEnabled = true;
1271 				}
1272 				glFrontFace(c.raster.frontFace);
1273 				glCullFace(c.raster.cullFace);
1274 			} else if (!c.raster.cullEnable && cullEnabled) {
1275 				glDisable(GL_CULL_FACE);
1276 				cullEnabled = false;
1277 			}
1278 			if (c.raster.ditherEnable) {
1279 				if (!ditherEnabled) {
1280 					glEnable(GL_DITHER);
1281 					ditherEnabled = true;
1282 				}
1283 			} else if (!c.raster.ditherEnable && ditherEnabled) {
1284 				glDisable(GL_DITHER);
1285 				ditherEnabled = false;
1286 			}
1287 #ifndef USING_GLES2
1288 			if (c.raster.depthClampEnable) {
1289 				if (!depthClampEnabled) {
1290 					glEnable(GL_DEPTH_CLAMP);
1291 					depthClampEnabled = true;
1292 				}
1293 			} else if (!c.raster.depthClampEnable && depthClampEnabled) {
1294 				glDisable(GL_DEPTH_CLAMP);
1295 				depthClampEnabled = false;
1296 			}
1297 #endif
1298 			CHECK_GL_ERROR_IF_DEBUG();
1299 			break;
1300 		default:
1301 			Crash();
1302 			break;
1303 		}
1304 	}
1305 
1306 	for (int i = 0; i < 7; i++) {
1307 		if (attrMask & (1 << i)) {
1308 			glDisableVertexAttribArray(i);
1309 		}
1310 	}
1311 
1312 	if (activeSlot != 0) {
1313 		glActiveTexture(GL_TEXTURE0);
1314 		activeSlot = 0;  // doesn't matter, just nice.
1315 	}
1316 	CHECK_GL_ERROR_IF_DEBUG();
1317 
1318 	// Wipe out the current state.
1319 	if (curArrayBuffer != 0)
1320 		glBindBuffer(GL_ARRAY_BUFFER, 0);
1321 	if (curElemArrayBuffer != 0)
1322 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1323 	if (last && gl_extensions.ARB_vertex_array_object) {
1324 		glBindVertexArray(0);
1325 	}
1326 	if (last)
1327 		glDisable(GL_SCISSOR_TEST);
1328 	if (depthEnabled)
1329 		glDisable(GL_DEPTH_TEST);
1330 	if (stencilEnabled)
1331 		glDisable(GL_STENCIL_TEST);
1332 	if (blendEnabled)
1333 		glDisable(GL_BLEND);
1334 	if (cullEnabled)
1335 		glDisable(GL_CULL_FACE);
1336 #ifndef USING_GLES2
1337 	if (depthClampEnabled)
1338 		glDisable(GL_DEPTH_CLAMP);
1339 	if (!gl_extensions.IsGLES && logicEnabled) {
1340 		glDisable(GL_COLOR_LOGIC_OP);
1341 	}
1342 #endif
1343 	if ((colorMask & 15) != 15)
1344 		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1345 	CHECK_GL_ERROR_IF_DEBUG();
1346 }
1347 
PerformCopy(const GLRStep & step)1348 void GLQueueRunner::PerformCopy(const GLRStep &step) {
1349 	CHECK_GL_ERROR_IF_DEBUG();
1350 	GLuint srcTex = 0;
1351 	GLuint dstTex = 0;
1352 	GLuint target = GL_TEXTURE_2D;
1353 
1354 	const GLRect2D &srcRect = step.copy.srcRect;
1355 	const GLOffset2D &dstPos = step.copy.dstPos;
1356 
1357 	GLRFramebuffer *src = step.copy.src;
1358 	GLRFramebuffer *dst = step.copy.dst;
1359 
1360 	int srcLevel = 0;
1361 	int dstLevel = 0;
1362 	int srcZ = 0;
1363 	int dstZ = 0;
1364 	int depth = 1;
1365 
1366 	switch (step.copy.aspectMask) {
1367 	case GL_COLOR_BUFFER_BIT:
1368 		srcTex = src->color_texture.texture;
1369 		dstTex = dst->color_texture.texture;
1370 		break;
1371 	case GL_DEPTH_BUFFER_BIT:
1372 		// TODO: Support depth copies.
1373 		_assert_msg_(false, "Depth copies not yet supported - soon");
1374 		target = GL_RENDERBUFFER;
1375 		/*
1376 		srcTex = src->depth.texture;
1377 		dstTex = src->depth.texture;
1378 		*/
1379 		break;
1380 	}
1381 
1382 	_dbg_assert_(srcTex);
1383 	_dbg_assert_(dstTex);
1384 
1385 #if defined(USING_GLES2)
1386 #if !PPSSPP_PLATFORM(IOS)
1387 	_assert_msg_(gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image, "Image copy extension expected");
1388 	glCopyImageSubDataOES(
1389 		srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
1390 		dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
1391 		srcRect.w, srcRect.h, depth);
1392 #endif
1393 #else
1394 	_assert_msg_(gl_extensions.ARB_copy_image || gl_extensions.NV_copy_image, "Image copy extension expected");
1395 	if (gl_extensions.ARB_copy_image) {
1396 		glCopyImageSubData(
1397 			srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
1398 			dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
1399 			srcRect.w, srcRect.h, depth);
1400 	} else if (gl_extensions.NV_copy_image) {
1401 		// Older, pre GL 4.x NVIDIA cards.
1402 		glCopyImageSubDataNV(
1403 			srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
1404 			dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
1405 			srcRect.w, srcRect.h, depth);
1406 	}
1407 #endif
1408 	CHECK_GL_ERROR_IF_DEBUG();
1409 }
1410 
PerformReadback(const GLRStep & pass)1411 void GLQueueRunner::PerformReadback(const GLRStep &pass) {
1412 	using namespace Draw;
1413 	CHECK_GL_ERROR_IF_DEBUG();
1414 
1415 	GLRFramebuffer *fb = pass.readback.src;
1416 
1417 	fbo_bind_fb_target(true, fb ? fb->handle : 0);
1418 
1419 	// Reads from the "bound for read" framebuffer. Note that if there's no fb, it's not valid to call this.
1420 	if (fb && (gl_extensions.GLES3 || !gl_extensions.IsGLES))
1421 		glReadBuffer(GL_COLOR_ATTACHMENT0);
1422 
1423 	CHECK_GL_ERROR_IF_DEBUG();
1424 
1425 	// Always read back in 8888 format for the color aspect.
1426 	GLuint internalFormat = GL_RGBA;
1427 	GLuint format = GL_RGBA;
1428 	GLuint type = GL_UNSIGNED_BYTE;
1429 	int srcAlignment = 4;
1430 	int dstAlignment = (int)DataFormatSizeInBytes(pass.readback.dstFormat);
1431 
1432 #ifndef USING_GLES2
1433 	if (pass.readback.aspectMask & GL_DEPTH_BUFFER_BIT) {
1434 		internalFormat = GL_DEPTH_COMPONENT;
1435 		format = GL_DEPTH_COMPONENT;
1436 		type = GL_FLOAT;
1437 		srcAlignment = 4;
1438 	} else if (pass.readback.aspectMask & GL_STENCIL_BUFFER_BIT) {
1439 		internalFormat = GL_STENCIL_INDEX;
1440 		format = GL_STENCIL_INDEX;
1441 		type = GL_UNSIGNED_BYTE;
1442 		srcAlignment = 1;
1443 	}
1444 #endif
1445 
1446 	int pixelStride = pass.readback.srcRect.w;
1447 	// Apply the correct alignment.
1448 	glPixelStorei(GL_PACK_ALIGNMENT, srcAlignment);
1449 	if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
1450 		// Some drivers seem to require we specify this.  See #8254.
1451 		glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride);
1452 	}
1453 
1454 	GLRect2D rect = pass.readback.srcRect;
1455 
1456 	bool convert = internalFormat == GL_RGBA && pass.readback.dstFormat != DataFormat::R8G8B8A8_UNORM;
1457 
1458 	int tempSize = srcAlignment * rect.w * rect.h;
1459 	int readbackSize = dstAlignment * rect.w * rect.h;
1460 	if (convert && tempSize > tempBufferSize_) {
1461 		delete[] tempBuffer_;
1462 		tempBuffer_ = new uint8_t[tempSize];
1463 		tempBufferSize_ = tempSize;
1464 	}
1465 	if (readbackSize > readbackBufferSize_) {
1466 		delete[] readbackBuffer_;
1467 		readbackBuffer_ = new uint8_t[readbackSize];
1468 		readbackBufferSize_ = readbackSize;
1469 	}
1470 
1471 	glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, convert ? tempBuffer_ : readbackBuffer_);
1472 	#ifdef DEBUG_READ_PIXELS
1473 	LogReadPixelsError(glGetError());
1474 	#endif
1475 	if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
1476 		glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1477 	}
1478 	if (convert && tempBuffer_ && readbackBuffer_) {
1479 		ConvertFromRGBA8888(readbackBuffer_, tempBuffer_, pixelStride, pixelStride, rect.w, rect.h, pass.readback.dstFormat);
1480 	}
1481 	CHECK_GL_ERROR_IF_DEBUG();
1482 }
1483 
PerformReadbackImage(const GLRStep & pass)1484 void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) {
1485 #ifndef USING_GLES2
1486 	GLRTexture *tex = pass.readback_image.texture;
1487 	GLRect2D rect = pass.readback_image.srcRect;
1488 
1489 	if (gl_extensions.VersionGEThan(4, 5)) {
1490 		int size = 4 * rect.w * rect.h;
1491 		if (size > readbackBufferSize_) {
1492 			delete[] readbackBuffer_;
1493 			readbackBuffer_ = new uint8_t[size];
1494 			readbackBufferSize_ = size;
1495 		}
1496 
1497 		glPixelStorei(GL_PACK_ALIGNMENT, 4);
1498 		glGetTextureSubImage(tex->texture, pass.readback_image.mipLevel, rect.x, rect.y, 0, rect.w, rect.h, 1, GL_RGBA, GL_UNSIGNED_BYTE, readbackBufferSize_, readbackBuffer_);
1499 	} else {
1500 		glBindTexture(GL_TEXTURE_2D, tex->texture);
1501 
1502 		CHECK_GL_ERROR_IF_DEBUG();
1503 
1504 		GLint w, h;
1505 		// This is only used for debugging (currently), and GL doesn't support a subrectangle.
1506 		glGetTexLevelParameteriv(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_TEXTURE_WIDTH, &w);
1507 		glGetTexLevelParameteriv(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_TEXTURE_HEIGHT, &h);
1508 
1509 		int size = 4 * std::max((int)w, rect.x + rect.w) * std::max((int)h, rect.h);
1510 		if (size > readbackBufferSize_) {
1511 			delete[] readbackBuffer_;
1512 			readbackBuffer_ = new uint8_t[size];
1513 			readbackBufferSize_ = size;
1514 		}
1515 
1516 		glPixelStorei(GL_PACK_ALIGNMENT, 4);
1517 		glPixelStorei(GL_PACK_ROW_LENGTH, rect.x + rect.w);
1518 		glGetTexImage(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_RGBA, GL_UNSIGNED_BYTE, readbackBuffer_);
1519 		glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1520 
1521 		if (rect.x != 0 || rect.y != 0) {
1522 			int dstStride = 4 * rect.w;
1523 			int srcStride = 4 * (rect.x + rect.w);
1524 			int xoff = 4 * rect.x;
1525 			int yoff = rect.y * srcStride;
1526 			for (int y = 0; y < rect.h; ++y) {
1527 				memmove(readbackBuffer_ + h * dstStride, readbackBuffer_ + yoff + h * srcStride + xoff, dstStride);
1528 			}
1529 		}
1530 	}
1531 #endif
1532 
1533 	CHECK_GL_ERROR_IF_DEBUG();
1534 }
1535 
PerformBindFramebufferAsRenderTarget(const GLRStep & pass)1536 void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) {
1537 	if (pass.render.framebuffer) {
1538 		curFBWidth_ = pass.render.framebuffer->width;
1539 		curFBHeight_ = pass.render.framebuffer->height;
1540 	} else {
1541 		curFBWidth_ = targetWidth_;
1542 		curFBHeight_ = targetHeight_;
1543 	}
1544 
1545 	curFB_ = pass.render.framebuffer;
1546 	if (curFB_) {
1547 		// Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing
1548 		// in ES 2.0 that actually separate them anyway of course, so doesn't matter.
1549 		fbo_bind_fb_target(false, curFB_->handle);
1550 	} else {
1551 		fbo_unbind();
1552 		// Backbuffer is now bound.
1553 	}
1554 	CHECK_GL_ERROR_IF_DEBUG();
1555 }
1556 
CopyReadbackBuffer(int width,int height,Draw::DataFormat srcFormat,Draw::DataFormat destFormat,int pixelStride,uint8_t * pixels)1557 void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) {
1558 	// TODO: Maybe move data format conversion here, and always read back 8888. Drivers
1559 	// don't usually provide very optimized conversion implementations, though some do.
1560 	// Just need to be careful about dithering, which may break Danganronpa.
1561 	int bpp = (int)Draw::DataFormatSizeInBytes(destFormat);
1562 	if (!readbackBuffer_ || bpp <= 0 || !pixels) {
1563 		// Something went wrong during the read and no readback buffer was allocated, probably.
1564 		return;
1565 	}
1566 	for (int y = 0; y < height; y++) {
1567 		memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, width * bpp);
1568 	}
1569 }
1570 
AllocTextureName()1571 GLuint GLQueueRunner::AllocTextureName() {
1572 	if (nameCache_.empty()) {
1573 		nameCache_.resize(TEXCACHE_NAME_CACHE_SIZE);
1574 		glGenTextures(TEXCACHE_NAME_CACHE_SIZE, &nameCache_[0]);
1575 	}
1576 	u32 name = nameCache_.back();
1577 	nameCache_.pop_back();
1578 	CHECK_GL_ERROR_IF_DEBUG();
1579 	return name;
1580 }
1581 
1582 // On PC, we always use GL_DEPTH24_STENCIL8.
1583 // On Android, we try to use what's available.
1584 
1585 #ifndef USING_GLES2
fbo_ext_create(const GLRInitStep & step)1586 void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) {
1587 	GLRFramebuffer *fbo = step.create_framebuffer.framebuffer;
1588 
1589 	CHECK_GL_ERROR_IF_DEBUG();
1590 
1591 	// Color texture is same everywhere
1592 	glGenFramebuffersEXT(1, &fbo->handle);
1593 	glGenTextures(1, &fbo->color_texture.texture);
1594 
1595 	// Create the surfaces.
1596 	glBindTexture(GL_TEXTURE_2D, fbo->color_texture.texture);
1597 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1598 
1599 	fbo->color_texture.target = GL_TEXTURE_2D;
1600 	fbo->color_texture.wrapS = GL_CLAMP_TO_EDGE;
1601 	fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE;
1602 	fbo->color_texture.magFilter = GL_LINEAR;
1603 	fbo->color_texture.minFilter = GL_LINEAR;
1604 	fbo->color_texture.maxLod = 0.0f;
1605 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS);
1606 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT);
1607 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fbo->color_texture.magFilter);
1608 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fbo->color_texture.minFilter);
1609 
1610 	fbo->stencil_buffer = 0;
1611 	fbo->z_buffer = 0;
1612 	// 24-bit Z, 8-bit stencil
1613 	glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer);
1614 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
1615 	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, fbo->width, fbo->height);
1616 	// glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height);
1617 
1618 	// Bind it all together
1619 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle);
1620 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
1621 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
1622 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
1623 
1624 	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1625 	switch (status) {
1626 	case GL_FRAMEBUFFER_COMPLETE_EXT:
1627 		// INFO_LOG(G3D, "Framebuffer verified complete.");
1628 		break;
1629 	case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
1630 		ERROR_LOG(G3D, "GL_FRAMEBUFFER_UNSUPPORTED");
1631 		break;
1632 	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
1633 		ERROR_LOG(G3D, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
1634 		break;
1635 	default:
1636 		_assert_msg_(false, "Other framebuffer error: %d", status);
1637 		break;
1638 	}
1639 	// Unbind state we don't need
1640 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1641 	glBindTexture(GL_TEXTURE_2D, 0);
1642 
1643 	CHECK_GL_ERROR_IF_DEBUG();
1644 
1645 	currentDrawHandle_ = fbo->handle;
1646 	currentReadHandle_ = fbo->handle;
1647 }
1648 #endif
1649 
fbo_get_fb_target(bool read,GLuint ** cached)1650 GLenum GLQueueRunner::fbo_get_fb_target(bool read, GLuint **cached) {
1651 	bool supportsBlit = gl_extensions.ARB_framebuffer_object;
1652 	if (gl_extensions.IsGLES) {
1653 		supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit);
1654 	}
1655 
1656 	// Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV.
1657 	if (supportsBlit) {
1658 		if (read) {
1659 			*cached = &currentReadHandle_;
1660 			return GL_READ_FRAMEBUFFER;
1661 		} else {
1662 			*cached = &currentDrawHandle_;
1663 			return GL_DRAW_FRAMEBUFFER;
1664 		}
1665 	} else {
1666 		*cached = &currentDrawHandle_;
1667 		return GL_FRAMEBUFFER;
1668 	}
1669 }
1670 
fbo_bind_fb_target(bool read,GLuint name)1671 void GLQueueRunner::fbo_bind_fb_target(bool read, GLuint name) {
1672 	CHECK_GL_ERROR_IF_DEBUG();
1673 	GLuint *cached;
1674 	GLenum target = fbo_get_fb_target(read, &cached);
1675 	if (*cached != name) {
1676 		if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
1677 			glBindFramebuffer(target, name);
1678 		} else {
1679 #ifndef USING_GLES2
1680 			glBindFramebufferEXT(target, name);
1681 #endif
1682 		}
1683 		*cached = name;
1684 	}
1685 	CHECK_GL_ERROR_IF_DEBUG();
1686 }
1687 
fbo_unbind()1688 void GLQueueRunner::fbo_unbind() {
1689 	CHECK_GL_ERROR_IF_DEBUG();
1690 #ifndef USING_GLES2
1691 	if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
1692 		glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
1693 	} else if (gl_extensions.EXT_framebuffer_object) {
1694 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO);
1695 	}
1696 #else
1697 	glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
1698 #endif
1699 
1700 #if PPSSPP_PLATFORM(IOS)
1701 	bindDefaultFBO();
1702 #endif
1703 
1704 	currentDrawHandle_ = 0;
1705 	currentReadHandle_ = 0;
1706 	CHECK_GL_ERROR_IF_DEBUG();
1707 }
1708 
~GLRFramebuffer()1709 GLRFramebuffer::~GLRFramebuffer() {
1710 	if (handle == 0 && z_stencil_buffer == 0 && z_buffer == 0 && stencil_buffer == 0)
1711 		return;
1712 
1713 	CHECK_GL_ERROR_IF_DEBUG();
1714 	if (handle) {
1715 		if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
1716 			glBindFramebuffer(GL_FRAMEBUFFER, handle);
1717 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1718 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
1719 			glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
1720 			glDeleteFramebuffers(1, &handle);
1721 #ifndef USING_GLES2
1722 		} else if (gl_extensions.EXT_framebuffer_object) {
1723 			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, handle);
1724 			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1725 			glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0);
1726 			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO);
1727 			glDeleteFramebuffersEXT(1, &handle);
1728 #endif
1729 		}
1730 	}
1731 
1732 	// These can only be set when supported.
1733 	if (z_stencil_buffer)
1734 		glDeleteRenderbuffers(1, &z_stencil_buffer);
1735 	if (z_buffer)
1736 		glDeleteRenderbuffers(1, &z_buffer);
1737 	if (stencil_buffer)
1738 		glDeleteRenderbuffers(1, &stencil_buffer);
1739 	CHECK_GL_ERROR_IF_DEBUG();
1740 }
1741