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