| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "spy.h" |
| |
| #include <gapic/coder/gles.h> |
| |
| // This file contains a number of GLES method 'overrides' to optionally lie to the |
| // application about the driver not supporting precompiled shaders or programs. |
| |
| namespace { |
| |
| const char* kOESGetProgramBinary = "OES_get_program_binary"; |
| const char* kReplacementExtension = "__GAPID_PCS_DISABLED__"; // Must be the same length as kOESGetProgramBinary |
| |
| } // anonymous namespace |
| |
| using gapic::coder::atom::Observations; |
| using namespace gapii::GLenum; |
| |
| namespace gapii { |
| |
| void Spy::glProgramBinary(uint32_t program, uint32_t binary_format, void* binary, |
| int32_t binary_size) { |
| if (mDisablePrecompiledShaders) { |
| // GL_INVALID_ENUM is generated if binaryformat is not a supported format returned in |
| // GL_SHADER_BINARY_FORMATS. |
| setFakeGlError(GL_INVALID_ENUM); |
| |
| gapic::coder::gles::GlProgramBinary coder( |
| mScratch.vector<gapic::Encodable*>(kMaxExtras), |
| program, |
| binary_format, |
| gapic::coder::gles::Void__CP(reinterpret_cast<uintptr_t>(binary), 0), |
| binary_size); |
| read(binary, binary_size); |
| observeReads(); |
| observeWrites(); |
| coder.mextras.append(&mObservations); |
| mEncoder->Variant(&coder); |
| } else { |
| GlesSpy::glProgramBinary(program, binary_format, binary, binary_size); |
| } |
| } |
| |
| void Spy::glProgramBinaryOES(uint32_t program, uint32_t binary_format, void* binary, |
| int32_t binary_size) { |
| if (mDisablePrecompiledShaders) { |
| // GL_INVALID_ENUM is generated if binaryformat is not a supported format returned in |
| // GL_SHADER_BINARY_FORMATS. |
| setFakeGlError(GL_INVALID_ENUM); |
| |
| gapic::coder::gles::GlProgramBinaryOES coder( |
| mScratch.vector<gapic::Encodable*>(kMaxExtras), |
| program, |
| binary_format, |
| gapic::coder::gles::Void__CP(reinterpret_cast<uintptr_t>(binary), 0), |
| binary_size); |
| read(binary, binary_size); |
| observeReads(); |
| observeWrites(); |
| coder.mextras.append(&mObservations); |
| mEncoder->Variant(&coder); |
| } else { |
| GlesSpy::glProgramBinaryOES(program, binary_format, binary, binary_size); |
| } |
| } |
| |
| void Spy::glShaderBinary(int32_t count, uint32_t* shaders, uint32_t binary_format, void* binary, |
| int32_t binary_size) { |
| if (mDisablePrecompiledShaders) { |
| // GL_INVALID_ENUM is generated if binaryFormat is not a value recognized by the implementation. |
| setFakeGlError(GL_INVALID_ENUM); |
| |
| read(slice(shaders, (uint64_t)((GLsizei)(0)), (uint64_t)(count))); |
| read(slice(binary, (uint64_t)((GLsizei)(0)), (uint64_t)(binary_size))); |
| observeReads(); |
| observeWrites(); |
| gapic::coder::gles::GlShaderBinary coder( |
| mScratch.vector<gapic::Encodable*>(kMaxExtras), |
| count, |
| gapic::coder::gles::ShaderId__CP(reinterpret_cast<uintptr_t>(shaders), 0), |
| binary_format, |
| gapic::coder::gles::Void__CP(reinterpret_cast<uintptr_t>(binary), 0), |
| binary_size); |
| coder.mextras.append(&mObservations); |
| mEncoder->Variant(&coder); |
| } else { |
| GlesSpy::glShaderBinary(count, shaders, binary_format, binary, binary_size); |
| } |
| } |
| |
| void Spy::glGetInteger64v(uint32_t param, int64_t* values) { |
| if (mDisablePrecompiledShaders && |
| (param == GL_NUM_SHADER_BINARY_FORMATS || param == GL_NUM_PROGRAM_BINARY_FORMATS)) { |
| values[0] = 0; |
| |
| observeReads(); |
| write(slice(values, 0, 1)); |
| observeWrites(); |
| gapic::coder::gles::GlGetInteger64v coder( |
| mScratch.vector<gapic::Encodable*>(kMaxExtras), |
| param, |
| gapic::coder::gles::GLint64__P(reinterpret_cast<uintptr_t>(values), 0)); |
| coder.mextras.append(&mObservations); |
| mEncoder->Variant(&coder); |
| } else { |
| GlesSpy::glGetInteger64v(param, values); |
| } |
| } |
| |
| void Spy::glGetIntegerv(uint32_t param, int32_t* values) { |
| if (mDisablePrecompiledShaders && |
| (param == GL_NUM_SHADER_BINARY_FORMATS || param == GL_NUM_PROGRAM_BINARY_FORMATS)) { |
| values[0] = 0; |
| |
| observeReads(); |
| write(slice(values, 0, 1)); |
| observeWrites(); |
| gapic::coder::gles::GlGetIntegerv coder( |
| mScratch.vector<gapic::Encodable*>(kMaxExtras), |
| param, |
| gapic::coder::gles::GLint__P(reinterpret_cast<uintptr_t>(values), 0)); |
| coder.mextras.append(&mObservations); |
| mEncoder->Variant(&coder); |
| } else { |
| GlesSpy::glGetIntegerv(param, values); |
| } |
| } |
| |
| GLubyte* Spy::glGetString(uint32_t name) { |
| if (mDisablePrecompiledShaders && name == GL_EXTENSIONS) { |
| std::string list = reinterpret_cast<const char*>(GlesSpy::mImports.glGetString(name)); |
| size_t start = list.find(kOESGetProgramBinary); |
| if (start != std::string::npos) { |
| static std::string copy = list; |
| copy.replace(start, strlen(kOESGetProgramBinary), kReplacementExtension); |
| // TODO: write atom. |
| return reinterpret_cast<GLubyte*>(const_cast<char*>(copy.c_str())); |
| } |
| } |
| return GlesSpy::glGetString(name); |
| } |
| |
| GLubyte* Spy::glGetStringi(uint32_t name, GLuint index) { |
| if (mDisablePrecompiledShaders && (name == GL_EXTENSIONS)) { |
| const char* extension = reinterpret_cast<const char*>(GlesSpy::mImports.glGetStringi(name, index)); |
| if (strcmp(extension, kOESGetProgramBinary) == 0) { |
| // TODO: write atom. |
| return reinterpret_cast<GLubyte*>(const_cast<char*>(kReplacementExtension)); |
| } |
| } |
| return GlesSpy::glGetStringi(name, index); |
| } |
| |
| |
| } // namespace gapii |