blob: 2c1b0c9765c2917b44f6f322feca189187b09eea [file] [log] [blame]
/*
* 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