blob: d3c4f72d946a7433c6aa1363304e443f1a449ab5 [file] [log] [blame]
/*
* Copyright 2015, 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.
*/
// Note this file is included in context in gles_spy.h:
//
// namespace gapii {
//
// class GlesSpy {
// protected:
typedef uint32_t GLenum_Error;
std::unordered_map<gapii::ContextID, GLenum_Error> mErrors;
template<typename T> T inline min(T a, T b) { return (a < b) ? a : b; }
template<typename T> T inline max(T a, T b) { return (a > b) ? a : b; }
// Externs not implemented in GAPII.
template <typename T> inline void mapMemory(const T&) {}
template <typename T> inline void unmapMemory(const T&) {}
template <typename T> inline void resolveAttributesAndUniforms(const T&, int32_t) {}
inline uint32_t minIndex(const uint8_t* indices, uint32_t indices_type, uint32_t offset, uint32_t count) {
uint32_t v = ~(uint32_t)0;
switch (indices_type) {
case gapii::GLenum::GL_UNSIGNED_BYTE: {
const uint8_t* p = reinterpret_cast<const uint8_t*>(&indices[offset]);
for (uint32_t i = 0; i < count; i++) { v = min<uint32_t>(v, p[i]); }
break;
}
case gapii::GLenum::GL_UNSIGNED_SHORT: {
const uint16_t* p = reinterpret_cast<const uint16_t*>(&indices[offset]);
for (uint32_t i = 0; i < count; i++) { v = min<uint32_t>(v, p[i]); }
break;
}
case gapii::GLenum::GL_UNSIGNED_INT: {
const uint32_t* p = reinterpret_cast<const uint32_t*>(&indices[offset]);
for (uint32_t i = 0; i < count; i++) { v = min<uint32_t>(v, p[i]); }
break;
}
}
return v;
}
inline uint32_t maxIndex(const uint8_t* indices, uint32_t indices_type, uint32_t offset, uint32_t count) {
uint32_t v = 0;
switch (indices_type) {
case gapii::GLenum::GL_UNSIGNED_BYTE: {
const uint8_t* p = reinterpret_cast<const uint8_t*>(&indices[offset]);
for (uint32_t i = 0; i < count; i++) { v = max<uint32_t>(v, p[i]); }
break;
}
case gapii::GLenum::GL_UNSIGNED_SHORT: {
const uint16_t* p = reinterpret_cast<const uint16_t*>(&indices[offset]);
for (uint32_t i = 0; i < count; i++) { v = max<uint32_t>(v, p[i]); }
break;
}
case gapii::GLenum::GL_UNSIGNED_INT: {
const uint32_t* p = reinterpret_cast<const uint32_t*>(&indices[offset]);
for (uint32_t i = 0; i < count; i++) { v = max<uint32_t>(v, p[i]); }
break;
}
}
return v;
}
inline int stateVariableSize(uint32_t v) {
switch (v) {
case GLenum::GL_ALIASED_LINE_WIDTH_RANGE:
return 2;
case GLenum::GL_ALIASED_POINT_SIZE_RANGE:
return 2;
case GLenum::GL_BLEND_COLOR:
return 4;
case GLenum::GL_COLOR_CLEAR_VALUE:
return 4;
case GLenum::GL_COLOR_WRITEMASK:
return 4;
case GLenum::GL_DEPTH_RANGE:
return 2;
case GLenum::GL_MAX_VIEWPORT_DIMS:
return 2;
case GLenum::GL_SCISSOR_BOX:
return 4;
case GLenum::GL_VIEWPORT:
return 4;
default:
return 1;
}
}
inline int pixelSize(uint32_t format, uint32_t type) {
int num_components = 0;
switch (format) {
case GLenum::GL_ALPHA:
num_components = 1;
break;
case GLenum::GL_LUMINANCE:
num_components = 1;
break;
case GLenum::GL_LUMINANCE_ALPHA:
num_components = 2;
break;
case GLenum::GL_RED:
num_components = 1;
break;
case GLenum::GL_RED_INTEGER:
num_components = 1;
break;
case GLenum::GL_RG:
num_components = 2;
break;
case GLenum::GL_RG_INTEGER:
num_components = 2;
break;
case GLenum::GL_RGB:
num_components = 3;
break;
case GLenum::GL_RGB_INTEGER:
num_components = 3;
break;
case GLenum::GL_RGBA:
num_components = 4;
break;
case GLenum::GL_RGBA_INTEGER:
num_components = 4;
break;
case GLenum::GL_DEPTH_COMPONENT:
num_components = 1;
break;
case GLenum::GL_DEPTH_STENCIL:
num_components = 2;
break;
case GLenum::GL_STENCIL_INDEX:
num_components = 1;
break;
}
switch(type) {
case GLenum::GL_UNSIGNED_BYTE:
return num_components * 1;
case GLenum::GL_BYTE:
return num_components * 1;
case GLenum::GL_UNSIGNED_SHORT:
return num_components * 2;
case GLenum::GL_SHORT:
return num_components * 2;
case GLenum::GL_UNSIGNED_INT:
return num_components * 4;
case GLenum::GL_INT:
return num_components * 4;
case GLenum::GL_HALF_FLOAT:
return num_components * 2;
case GLenum::GL_HALF_FLOAT_OES:
return num_components * 2;
case GLenum::GL_FLOAT:
return num_components * 4;
case GLenum::GL_UNSIGNED_SHORT_5_6_5:
return 2;
case GLenum::GL_UNSIGNED_SHORT_4_4_4_4:
return 2;
case GLenum::GL_UNSIGNED_SHORT_5_5_5_1:
return 2;
case GLenum::GL_UNSIGNED_INT_2_10_10_10_REV:
return 4;
case GLenum::GL_UNSIGNED_INT_10F_11F_11F_REV:
return 4;
case GLenum::GL_UNSIGNED_INT_5_9_9_9_REV:
return 4;
case GLenum::GL_UNSIGNED_INT_24_8:
return 4;
case GLenum::GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
return 8;
default:
return 0; // TODO: Assert?
}
}
inline void onGlError(std::shared_ptr<gapii::Context> ctx, GLenum_Error err) {
switch (err) {
case GLenum::GL_INVALID_ENUM:
GAPID_WARNING("Error calling %s: GL_INVALID_ENUM", mCurrentCommandName);
break;
case GLenum::GL_INVALID_VALUE:
GAPID_WARNING("Error calling %s: GL_INVALID_VALUE", mCurrentCommandName);
break;
case GLenum::GL_INVALID_OPERATION:
GAPID_WARNING("Error calling %s: GL_INVALID_OPERATION", mCurrentCommandName);
break;
case GLenum::GL_STACK_OVERFLOW:
GAPID_WARNING("Error calling %s: GL_STACK_OVERFLOW", mCurrentCommandName);
break;
case GLenum::GL_STACK_UNDERFLOW:
GAPID_WARNING("Error calling %s: GL_STACK_UNDERFLOW", mCurrentCommandName);
break;
case GLenum::GL_OUT_OF_MEMORY:
GAPID_WARNING("Error calling %s: GL_OUT_OF_MEMORY", mCurrentCommandName);
break;
case GLenum::GL_INVALID_FRAMEBUFFER_OPERATION:
GAPID_WARNING("Error calling %s: GL_INVALID_FRAMEBUFFER_OPERATION", mCurrentCommandName);
break;
case GLenum::GL_CONTEXT_LOST:
GAPID_WARNING("Error calling %s: GL_CONTEXT_LOST", mCurrentCommandName);
break;
default:
GAPID_WARNING("Error calling %s: %d", mCurrentCommandName, err);
break;
}
if (ctx == nullptr) {
GAPID_WARNING("Error raised with no context. Aborting command.");
abort();
return;
}
// If no current value then initialize, otherwise update if not GL_NO_ERROR
auto ret = mErrors.insert(std::make_pair(ctx->mIdentifier, err));
bool inserted = ret.second;
if (!inserted) {
auto& value = ret.first->second;
if (value == GLenum::GL_NO_ERROR) {
// Per spec flag is only update if it is not set.
value = err;
}
}
}
inline GLenum_Error getAndClearAnErrorFlag(std::shared_ptr<gapii::Context> ctx) {
if (ctx == nullptr) {
return GLenum::GL_INVALID_OPERATION;
}
// lookup the value, use GL_NO_ERROR as the default, clear the value.
auto it = mErrors.find(ctx->mIdentifier);
auto err = GLenum::GL_NO_ERROR;
if (it == mErrors.end()) {
return err;
}
std::swap(it->second, err);
return err;
}