Home | History | Annotate | Download | only in service
      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