1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "gpu/command_buffer/service/error_state.h" 6 7 #include <string> 8 9 #include "base/strings/stringprintf.h" 10 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 11 #include "gpu/command_buffer/service/logger.h" 12 #include "ui/gl/gl_bindings.h" 13 14 namespace gpu { 15 namespace gles2 { 16 17 class ErrorStateImpl : public ErrorState { 18 public: 19 explicit ErrorStateImpl(ErrorStateClient* client, Logger* logger); 20 virtual ~ErrorStateImpl(); 21 22 virtual uint32 GetGLError() OVERRIDE; 23 24 virtual void SetGLError( 25 const char* filename, 26 int line, 27 unsigned int error, 28 const char* function_name, 29 const char* msg) OVERRIDE; 30 virtual void SetGLErrorInvalidEnum( 31 const char* filename, 32 int line, 33 const char* function_name, 34 unsigned int value, 35 const char* label) OVERRIDE; 36 virtual void SetGLErrorInvalidParami( 37 const char* filename, 38 int line, 39 unsigned int error, 40 const char* function_name, 41 unsigned int pname, 42 int param) OVERRIDE; 43 virtual void SetGLErrorInvalidParamf( 44 const char* filename, 45 int line, 46 unsigned int error, 47 const char* function_name, 48 unsigned int pname, 49 float param) OVERRIDE; 50 51 virtual unsigned int PeekGLError( 52 const char* filename, int line, const char* function_name) OVERRIDE; 53 54 virtual void CopyRealGLErrorsToWrapper( 55 const char* filename, int line, const char* function_name) OVERRIDE; 56 57 virtual void ClearRealGLErrors( 58 const char* filename, int line, const char* function_name) OVERRIDE; 59 60 private: 61 // The last error message set. 62 std::string last_error_; 63 // Current GL error bits. 64 uint32 error_bits_; 65 66 ErrorStateClient* client_; 67 Logger* logger_; 68 69 DISALLOW_COPY_AND_ASSIGN(ErrorStateImpl); 70 }; 71 72 ErrorState::ErrorState() {} 73 74 ErrorState::~ErrorState() {} 75 76 ErrorState* ErrorState::Create(ErrorStateClient* client, Logger* logger) { 77 return new ErrorStateImpl(client, logger); 78 } 79 80 ErrorStateImpl::ErrorStateImpl(ErrorStateClient* client, Logger* logger) 81 : error_bits_(0), client_(client), logger_(logger) {} 82 83 ErrorStateImpl::~ErrorStateImpl() {} 84 85 uint32 ErrorStateImpl::GetGLError() { 86 // Check the GL error first, then our wrapped error. 87 GLenum error = glGetError(); 88 if (error == GL_NO_ERROR && error_bits_ != 0) { 89 for (uint32 mask = 1; mask != 0; mask = mask << 1) { 90 if ((error_bits_ & mask) != 0) { 91 error = GLES2Util::GLErrorBitToGLError(mask); 92 break; 93 } 94 } 95 } 96 97 if (error != GL_NO_ERROR) { 98 // There was an error, clear the corresponding wrapped error. 99 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error); 100 } 101 return error; 102 } 103 104 unsigned int ErrorStateImpl::PeekGLError( 105 const char* filename, int line, const char* function_name) { 106 GLenum error = glGetError(); 107 if (error != GL_NO_ERROR) { 108 SetGLError(filename, line, error, function_name, ""); 109 } 110 return error; 111 } 112 113 void ErrorStateImpl::SetGLError( 114 const char* filename, 115 int line, 116 unsigned int error, 117 const char* function_name, 118 const char* msg) { 119 if (msg) { 120 last_error_ = msg; 121 logger_->LogMessage( 122 filename, line, 123 std::string("GL ERROR :") + 124 GLES2Util::GetStringEnum(error) + " : " + 125 function_name + ": " + msg); 126 } 127 error_bits_ |= GLES2Util::GLErrorToErrorBit(error); 128 if (error == GL_OUT_OF_MEMORY) 129 client_->OnOutOfMemoryError(); 130 } 131 132 void ErrorStateImpl::SetGLErrorInvalidEnum( 133 const char* filename, 134 int line, 135 const char* function_name, 136 unsigned int value, 137 const char* label) { 138 SetGLError(filename, line, GL_INVALID_ENUM, function_name, 139 (std::string(label) + " was " + 140 GLES2Util::GetStringEnum(value)).c_str()); 141 } 142 143 void ErrorStateImpl::SetGLErrorInvalidParami( 144 const char* filename, 145 int line, 146 unsigned int error, 147 const char* function_name, 148 unsigned int pname, int param) { 149 if (error == GL_INVALID_ENUM) { 150 SetGLError( 151 filename, line, GL_INVALID_ENUM, function_name, 152 (std::string("trying to set ") + 153 GLES2Util::GetStringEnum(pname) + " to " + 154 GLES2Util::GetStringEnum(param)).c_str()); 155 } else { 156 SetGLError( 157 filename, line, error, function_name, 158 (std::string("trying to set ") + 159 GLES2Util::GetStringEnum(pname) + " to " + 160 base::StringPrintf("%d", param)).c_str()); 161 } 162 } 163 164 void ErrorStateImpl::SetGLErrorInvalidParamf( 165 const char* filename, 166 int line, 167 unsigned int error, 168 const char* function_name, 169 unsigned int pname, float param) { 170 SetGLError( 171 filename, line, error, function_name, 172 (std::string("trying to set ") + 173 GLES2Util::GetStringEnum(pname) + " to " + 174 base::StringPrintf("%G", param)).c_str()); 175 } 176 177 void ErrorStateImpl::CopyRealGLErrorsToWrapper( 178 const char* filename, int line, const char* function_name) { 179 GLenum error; 180 while ((error = glGetError()) != GL_NO_ERROR) { 181 SetGLError(filename, line, error, function_name, 182 "<- error from previous GL command"); 183 } 184 } 185 186 void ErrorStateImpl::ClearRealGLErrors( 187 const char* filename, int line, const char* function_name) { 188 // Clears and logs all current gl errors. 189 GLenum error; 190 while ((error = glGetError()) != GL_NO_ERROR) { 191 if (error != GL_OUT_OF_MEMORY) { 192 // GL_OUT_OF_MEMORY can legally happen on lost device. 193 logger_->LogMessage( 194 filename, line, 195 std::string("GL ERROR :") + 196 GLES2Util::GetStringEnum(error) + " : " + 197 function_name + ": was unhandled"); 198 NOTREACHED() << "GL error " << error << " was unhandled."; 199 } 200 } 201 } 202 203 } // namespace gles2 204 } // namespace gpu 205 206