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 35namespace { 36 37class 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 85GLES2DemoInstance::GLES2DemoInstance(PP_Instance instance, pp::Module* module) 86 : pp::Instance(instance), pp::Graphics3DClient(this), 87 callback_factory_(this), 88 gles2_if_(static_cast<const PPB_OpenGLES2*>( 89 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE))), 90 module_(module), 91 context_(NULL), 92 fullscreen_(false) { 93 assert(gles2_if_); 94 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); 95} 96 97GLES2DemoInstance::~GLES2DemoInstance() { 98 delete context_; 99} 100 101void GLES2DemoInstance::DidChangeView( 102 const pp::Rect& position, const pp::Rect& clip_ignored) { 103 if (position.width() == 0 || position.height() == 0) 104 return; 105 plugin_size_ = position.size(); 106 107 // Initialize graphics. 108 InitGL(0); 109} 110 111// This object is the global object representing this plugin library as long 112// as it is loaded. 113class GLES2DemoModule : public pp::Module { 114 public: 115 GLES2DemoModule() : pp::Module() {} 116 virtual ~GLES2DemoModule() {} 117 118 virtual pp::Instance* CreateInstance(PP_Instance instance) { 119 return new GLES2DemoInstance(instance, this); 120 } 121}; 122 123void GLES2DemoInstance::InitGL(int32_t result) { 124 assert(plugin_size_.width() && plugin_size_.height()); 125 126 if (context_) { 127 context_->ResizeBuffers(plugin_size_.width(), plugin_size_.height()); 128 return; 129 } 130 int32_t context_attributes[] = { 131 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, 132 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, 133 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, 134 PP_GRAPHICS3DATTRIB_RED_SIZE, 8, 135 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, 136 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0, 137 PP_GRAPHICS3DATTRIB_SAMPLES, 0, 138 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, 139 PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(), 140 PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(), 141 PP_GRAPHICS3DATTRIB_NONE, 142 }; 143 context_ = new pp::Graphics3D(this, context_attributes); 144 assert(!context_->is_null()); 145 assert(BindGraphics(*context_)); 146 147 // Clear color bit. 148 gles2_if_->ClearColor(context_->pp_resource(), 0, 1, 0, 1); 149 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); 150 151 assertNoGLError(); 152 153 FlickerAndPaint(0, true); 154} 155 156void GLES2DemoInstance::FlickerAndPaint(int32_t result, bool paint_blue) { 157 if (result != 0 || !context_) 158 return; 159 float r = paint_blue ? 0 : 1; 160 float g = 0; 161 float b = paint_blue ? 1 : 0; 162 float a = 0.75; 163 gles2_if_->ClearColor(context_->pp_resource(), r, g, b, a); 164 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); 165 assertNoGLError(); 166 167 pp::CompletionCallback cb = callback_factory_.NewCallback( 168 &GLES2DemoInstance::FlickerAndPaint, !paint_blue); 169 context_->SwapBuffers(cb); 170 assertNoGLError(); 171} 172 173} // anonymous namespace 174 175namespace pp { 176// Factory function for your specialization of the Module object. 177Module* CreateModule() { 178 return new GLES2DemoModule(); 179} 180} // namespace pp 181