1 // Copyright (c) 2012 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 <string.h> 6 7 #include <iostream> 8 #include <sstream> 9 10 #include "ppapi/c/pp_errors.h" 11 #include "ppapi/c/ppb_opengles2.h" 12 #include "ppapi/cpp/core.h" 13 #include "ppapi/cpp/fullscreen.h" 14 #include "ppapi/cpp/graphics_3d.h" 15 #include "ppapi/cpp/graphics_3d_client.h" 16 #include "ppapi/cpp/input_event.h" 17 #include "ppapi/cpp/instance.h" 18 #include "ppapi/cpp/module.h" 19 #include "ppapi/cpp/rect.h" 20 #include "ppapi/cpp/var.h" 21 #include "ppapi/lib/gl/include/GLES2/gl2.h" 22 #include "ppapi/utility/completion_callback_factory.h" 23 24 // Use assert as a poor-man's CHECK, even in non-debug mode. 25 // Since <assert.h> redefines assert on every inclusion (it doesn't use 26 // include-guards), make sure this is the last file #include'd in this file. 27 #undef NDEBUG 28 #include <assert.h> 29 30 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a 31 // function to preserve line number information in the failure message. 32 #define assertNoGLError() \ 33 assert(!gles2_if_->GetError(context_->pp_resource())); 34 35 namespace { 36 37 class GLES2DemoInstance : public pp::Instance, 38 public pp::Graphics3DClient { 39 public: 40 GLES2DemoInstance(PP_Instance instance, pp::Module* module); 41 virtual ~GLES2DemoInstance(); 42 43 // pp::Instance implementation (see PPP_Instance). 44 virtual void DidChangeView(const pp::Rect& position, 45 const pp::Rect& clip_ignored); 46 47 // pp::Graphics3DClient implementation. 48 virtual void Graphics3DContextLost() { 49 // TODO(jamesr): What's the state of context_? Should we delete the old one 50 // or try to revive it somehow? 51 // For now, just delete it and construct+bind a new context. 52 delete context_; 53 context_ = NULL; 54 pp::CompletionCallback cb = callback_factory_.NewCallback( 55 &GLES2DemoInstance::InitGL); 56 module_->core()->CallOnMainThread(0, cb, 0); 57 } 58 59 virtual bool HandleInputEvent(const pp::InputEvent& event) { 60 if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEUP) { 61 fullscreen_ = !fullscreen_; 62 pp::Fullscreen(this).SetFullscreen(fullscreen_); 63 } 64 return true; 65 } 66 67 private: 68 69 // GL-related functions. 70 void InitGL(int32_t result); 71 void FlickerAndPaint(int32_t result, bool paint_blue); 72 73 pp::Size plugin_size_; 74 pp::CompletionCallbackFactory<GLES2DemoInstance> callback_factory_; 75 76 // Unowned pointers. 77 const PPB_OpenGLES2* gles2_if_; 78 pp::Module* module_; 79 80 // Owned data. 81 pp::Graphics3D* context_; 82 bool fullscreen_; 83 }; 84 85 GLES2DemoInstance::GLES2DemoInstance(PP_Instance instance, pp::Module* module) 86 : pp::Instance(instance), pp::Graphics3DClient(this), 87 callback_factory_(this), 88 module_(module), 89 context_(NULL), 90 fullscreen_(false) { 91 assert((gles2_if_ = static_cast<const PPB_OpenGLES2*>( 92 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)))); 93 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); 94 } 95 96 GLES2DemoInstance::~GLES2DemoInstance() { 97 delete context_; 98 } 99 100 void GLES2DemoInstance::DidChangeView( 101 const pp::Rect& position, const pp::Rect& clip_ignored) { 102 if (position.width() == 0 || position.height() == 0) 103 return; 104 plugin_size_ = position.size(); 105 106 // Initialize graphics. 107 InitGL(0); 108 } 109 110 // This object is the global object representing this plugin library as long 111 // as it is loaded. 112 class GLES2DemoModule : public pp::Module { 113 public: 114 GLES2DemoModule() : pp::Module() {} 115 virtual ~GLES2DemoModule() {} 116 117 virtual pp::Instance* CreateInstance(PP_Instance instance) { 118 return new GLES2DemoInstance(instance, this); 119 } 120 }; 121 122 void GLES2DemoInstance::InitGL(int32_t result) { 123 assert(plugin_size_.width() && plugin_size_.height()); 124 125 if (context_) { 126 context_->ResizeBuffers(plugin_size_.width(), plugin_size_.height()); 127 return; 128 } 129 int32_t context_attributes[] = { 130 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, 131 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, 132 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, 133 PP_GRAPHICS3DATTRIB_RED_SIZE, 8, 134 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, 135 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0, 136 PP_GRAPHICS3DATTRIB_SAMPLES, 0, 137 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, 138 PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(), 139 PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(), 140 PP_GRAPHICS3DATTRIB_NONE, 141 }; 142 context_ = new pp::Graphics3D(this, context_attributes); 143 assert(!context_->is_null()); 144 assert(BindGraphics(*context_)); 145 146 // Clear color bit. 147 gles2_if_->ClearColor(context_->pp_resource(), 0, 1, 0, 1); 148 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); 149 150 assertNoGLError(); 151 152 FlickerAndPaint(0, true); 153 } 154 155 void GLES2DemoInstance::FlickerAndPaint(int32_t result, bool paint_blue) { 156 if (result != 0 || !context_) 157 return; 158 float r = paint_blue ? 0 : 1; 159 float g = 0; 160 float b = paint_blue ? 1 : 0; 161 float a = 0.75; 162 gles2_if_->ClearColor(context_->pp_resource(), r, g, b, a); 163 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); 164 assertNoGLError(); 165 166 pp::CompletionCallback cb = callback_factory_.NewCallback( 167 &GLES2DemoInstance::FlickerAndPaint, !paint_blue); 168 context_->SwapBuffers(cb); 169 assertNoGLError(); 170 } 171 172 } // anonymous namespace 173 174 namespace pp { 175 // Factory function for your specialization of the Module object. 176 Module* CreateModule() { 177 return new GLES2DemoModule(); 178 } 179 } // namespace pp 180