compositor.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
12b8ee6c2994f738e5162ff46b638974870f51662Steve Naroff// Copyright 2014 The Chromium Authors. All rights reserved.
250398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff// Use of this source code is governed by a BSD-style license that can be
350398199fb10e196a8d92fbf7a062dbe42ed88fdSteve Naroff// found in the LICENSE file.
41e5e6684b0f27701e6f7c65f8c6a32a10cbcc3edDouglas Gregor
50c8296dfb495f41d6f0de6fe1d03014ffd063674Douglas Gregor// Needed on Windows to get |M_PI| from math.h.
689922f86f4e7da383af2a62ef04ad8b93b941220Steve Naroff#ifdef _WIN32
7af08ddc8f1c53fed8d8d0ad82aa2a0bb7d654bd1Steve Naroff#define _USE_MATH_DEFINES
8f2c87bd0368775927ead93e0dee3e4f3ca3f9a63Douglas Gregor#endif
9af08ddc8f1c53fed8d8d0ad82aa2a0bb7d654bd1Steve Naroff
100d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek#include <math.h>
110d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
120d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek#include <vector>
130d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
142e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/c/pp_errors.h"
152e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/c/pp_input_event.h"
162e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/compositor.h"
172e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/compositor_layer.h"
182e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/graphics_3d.h"
192e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/graphics_3d_client.h"
202e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/image_data.h"
212e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/input_event.h"
222e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/instance.h"
232e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/module.h"
242e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/rect.h"
252e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/cpp/var_dictionary.h"
262e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/examples/compositor/spinning_cube.h"
272e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
282e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/lib/gl/include/GLES2/gl2.h"
29ff9e18cb3863defa98257500ef49d93a9d2bc216Steve Naroff#include "ppapi/lib/gl/include/GLES2/gl2ext.h"
302e06fc877a633abea3b40a64950c7316dac29ca8John Thompson#include "ppapi/utility/completion_callback_factory.h"
31ff9e18cb3863defa98257500ef49d93a9d2bc216Steve Naroff
3245ba9a1b31110568d0d362c8d31c6133cf9011b7Douglas Gregor// Use assert as a poor-man's CHECK, even in non-debug mode.
3344c181aec37789f25f6c15543c164416f72e562aDouglas Gregor// Since <assert.h> redefines assert on every inclusion (it doesn't use
3444c181aec37789f25f6c15543c164416f72e562aDouglas Gregor// include-guards), make sure this is the last file #include'd in this file.
3544c181aec37789f25f6c15543c164416f72e562aDouglas Gregor#undef NDEBUG
3644c181aec37789f25f6c15543c164416f72e562aDouglas Gregor#include <assert.h>
37b1c031be513705d924038f497279b9b599868ba1Douglas Gregor
3887c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor// When compiling natively on Windows, PostMessage can be #define-d to
3987c08a5d6b9e1e44ae6f554df40139d3a6f60b33Douglas Gregor// something else.
40dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor#ifdef PostMessage
41dca8ee8b7bc86076916a3a80f553f7a4e98c14afDouglas Gregor#undef PostMessage
4244c181aec37789f25f6c15543c164416f72e562aDouglas Gregor#endif
4344c181aec37789f25f6c15543c164416f72e562aDouglas Gregor
4444c181aec37789f25f6c15543c164416f72e562aDouglas Gregor// Assert |context_| isn't holding any GL Errors.  Done as a macro instead of a
4544c181aec37789f25f6c15543c164416f72e562aDouglas Gregor// function to preserve line number information in the failure message.
4651b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar#define AssertNoGLError() \
4751b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar  PP_DCHECK(!glGetError());
4851b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar
49d52864bd33c66aacc84133460d8c9c0dfcdd5c18Daniel Dunbarnamespace {
5051b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar
5151b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbarconst int32_t kTextureWidth = 800;
521c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenekconst int32_t kTextureHeight = 800;
531c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenekconst int32_t kImageWidth = 256;
54e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenekconst int32_t kImageHeight = 256;
55a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor
566be2a22979e6a4af575af32cccdf6a6190a8edcaDan Gohmanclass DemoInstance : public pp::Instance, public pp::Graphics3DClient {
571c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek public:
581c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  DemoInstance(PP_Instance instance);
59e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  virtual ~DemoInstance();
601c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek
611c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  // pp::Instance implementation (see PPP_Instance).
621c6da1735ddc5978a2c24394c5112b4868b347f0Ted Kremenek  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
634db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  virtual void DidChangeView(const pp::Rect& position,
644db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                             const pp::Rect& clip);
654db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  virtual bool HandleInputEvent(const pp::InputEvent& event);
664db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
674db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  // pp::Graphics3DClient implementation.
684db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  virtual void Graphics3DContextLost();
694db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
70653a55f4bc0cb1d0c1f3ff86e9559f744eb3c18fDouglas Gregor private:
714db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  // GL-related functions.
724db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  void InitGL(int32_t result);
734db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  GLuint PrepareFramebuffer();
744db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  pp::ImageData PrepareImage();
754db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  void PrepareLayers(int32_t frame);
764db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  void Paint(int32_t result, int32_t frame);
774db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  void OnTextureReleased(int32_t result, GLuint texture);
784db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  void OnImageReleased(int32_t result, const pp::ImageData& image);
794db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
804db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  pp::CompletionCallbackFactory<DemoInstance> callback_factory_;
81e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
824db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  // Owned data.
834db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  pp::Graphics3D* context_;
844db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
854db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  GLuint fbo_;
86e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  GLuint rbo_;
874db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
884db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  std::vector<GLuint> textures_;
89e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  std::vector<pp::ImageData> images_;
904db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
914db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  pp::Compositor compositor_;
92e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  pp::CompositorLayer color_layer_;
934db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  pp::CompositorLayer stable_texture_layer_;
94653a55f4bc0cb1d0c1f3ff86e9559f744eb3c18fDouglas Gregor  pp::CompositorLayer texture_layer_;
95653a55f4bc0cb1d0c1f3ff86e9559f744eb3c18fDouglas Gregor  pp::CompositorLayer image_layer_;
964db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
974db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  bool rebuild_layers_;
984db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  int32_t total_resource_;
994db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1004db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  SpinningCube* cube_;
1014db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor};
1024db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1034db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas GregorDemoInstance::DemoInstance(PP_Instance instance)
1044db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    : pp::Instance(instance),
105e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      pp::Graphics3DClient(this),
1064db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      callback_factory_(this),
1074db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      context_(NULL),
1084db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      fbo_(0),
1094db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      rbo_(0),
1104db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      rebuild_layers_(true),
1114db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      total_resource_(0),
112e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      cube_(new SpinningCube()) {
1134db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
114c44fe4bf2962bfcb323e93a63ba4a72d67839cdeFrancois Pichet}
1154db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1164db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas GregorDemoInstance::~DemoInstance() {
1174db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  delete cube_;
1184db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  assert(glTerminatePPAPI());
1194db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  delete context_;
1204db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor}
1214db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1224db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregorbool DemoInstance::Init(uint32_t /*argc*/,
123e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek                        const char* /*argn*/[],
1244db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor                        const char* /*argv*/[]) {
1254db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  return !!glInitializePPAPI(pp::Module::Get()->get_browser_interface());
1264db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor}
1274db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
128e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenekvoid DemoInstance::DidChangeView(
1294db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    const pp::Rect& position, const pp::Rect& /*clip*/) {
1304db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  if (position.width() == 0 || position.height() == 0)
1314db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    return;
1324db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  // Initialize graphics.
1334db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  InitGL(0);
1344db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor}
1354db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1364db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregorbool DemoInstance::HandleInputEvent(const pp::InputEvent& event) {
1374db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  switch (event.GetType()) {
1384db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    case PP_INPUTEVENT_TYPE_MOUSEDOWN:
1394db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      rebuild_layers_ = true;
1404db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor      return true;
1414db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor    default:
142e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      break;
1434db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  }
1444db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  return false;
145e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek}
1464db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor
1474db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregorvoid DemoInstance::Graphics3DContextLost() {
1484db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  fbo_ = 0;
1494db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  rbo_ = 0;
1504db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  rebuild_layers_ = true;
1514db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  total_resource_ -= static_cast<int32_t>(textures_.size());
1524db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  textures_.clear();
153e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  delete context_;
1544db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  context_ = NULL;
1554db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  cube_->OnGLContextLost();
1564db64a461cb3442934afe43c83ed3f17f7c11c1dDouglas Gregor  pp::CompletionCallback cb = callback_factory_.NewCallback(
1570d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek      &DemoInstance::InitGL);
1580d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek  pp::Module::Get()->core()->CallOnMainThread(0, cb, 0);
1590d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek}
1600d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
161358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregorvoid DemoInstance::InitGL(int32_t /*result*/) {
162358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor  if (context_)
163dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor    return;
164e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  int32_t context_attributes[] = {
165e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
166e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
167e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
168e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
169699a07d8a0b1579c5178b3baf4bcf9edb6b38108Steve Naroff    PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
170e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek    PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
171c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor    PP_GRAPHICS3DATTRIB_SAMPLES, 0,
1721db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor    PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
173e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    PP_GRAPHICS3DATTRIB_WIDTH, 32,
1749f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    PP_GRAPHICS3DATTRIB_HEIGHT, 32,
1759f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    PP_GRAPHICS3DATTRIB_NONE,
1769f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor  };
177e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  context_ = new pp::Graphics3D(this, context_attributes);
178358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor  assert(!context_->is_null());
179358559d8d7b458c5f64941842383a16e61f0828dDouglas Gregor  assert(BindGraphics(compositor_));
180e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
181e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  glSetCurrentContextPPAPI(context_->pp_resource());
182e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
183ef0cef6cec8de5fc60e469a93436eed7212e0dc2Steve Naroff  cube_->Init(kTextureWidth, kTextureHeight);
184e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
185c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor  Paint(PP_OK, 0);
186c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor}
1871f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
1881f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas GregorGLuint DemoInstance::PrepareFramebuffer() {
1891f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  GLuint texture = 0;
1901f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  if (textures_.empty()) {
1911f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    total_resource_++;
1921f6206ed21e026ca7ddaf0bff9599c476301a695Douglas Gregor    // Create a texture object
1931f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glGenTextures(1, &texture);
1941f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glBindTexture(GL_TEXTURE_2D, texture);
1951f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0,
1961f6206ed21e026ca7ddaf0bff9599c476301a695Douglas Gregor                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
197a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1981f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1991f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2001f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2011f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    glBindTexture(GL_TEXTURE_2D, 0);
2021f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  } else {
203a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    texture = textures_.back();
2041f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    textures_.pop_back();
2051f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  }
206c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3fDouglas Gregor
207b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor  if (!rbo_) {
208b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor    // create a renderbuffer object to store depth info
209b699866820102a69d83d6ac6941985c5ef4e8c40Douglas Gregor    glGenRenderbuffers(1, &rbo_);
21058ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    glBindRenderbuffer(GL_RENDERBUFFER, rbo_);
21158ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
21258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor        kTextureWidth, kTextureHeight);
21358ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    glBindRenderbuffer(GL_RENDERBUFFER, 0);
21458ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  }
21558ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
21658ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  if (!fbo_) {
21758ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    // create a framebuffer object
21858ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor    glGenFramebuffers(1, &fbo_);
21958ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  }
22058ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
22158ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
22258ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor
22395f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek  // attach the texture to FBO color attachment point
224b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor  glFramebufferTexture2D(GL_FRAMEBUFFER,
225b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor                         GL_COLOR_ATTACHMENT0,
226b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor                         GL_TEXTURE_2D,
227b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor                         texture,
228b83d4d7071cea43a3f7b8afc3cda6203c345aa0fDouglas Gregor                         0);
22995f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek
23095f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek  // attach the renderbuffer to depth attachment point
23195f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek  glFramebufferRenderbuffer(GL_FRAMEBUFFER,
23295f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek                            GL_DEPTH_ATTACHMENT,
23395f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek                            GL_RENDERBUFFER,
23495f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek                            rbo_);
23595f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek
2363064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  // check FBO status
2373064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
2383064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  assert(status == GL_FRAMEBUFFER_COMPLETE);
2393064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek
2403064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  AssertNoGLError();
2413064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  return texture;
2423064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek}
2433064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek
2443064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenekpp::ImageData DemoInstance::PrepareImage() {
2453064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  if (images_.empty()) {
2463064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek    total_resource_++;
2473064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek    return pp::ImageData(this,
2483064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek                         PP_IMAGEDATAFORMAT_RGBA_PREMUL,
2493064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek                         pp::Size(kImageWidth, kImageHeight),
2503064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek                         false);
2513064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  }
2523064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  pp::ImageData image = images_.back();
2533064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  images_.pop_back();
2543064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  return image;
2553064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek}
256e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
257e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregorvoid DemoInstance::Paint(int32_t result, int32_t frame) {
258e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  assert(result == PP_OK);
259e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  if (result != PP_OK || !context_)
260e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    return;
261a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor
262e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  if (rebuild_layers_) {
263e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    compositor_ = pp::Compositor(this);
264e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    assert(BindGraphics(compositor_));
265e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    color_layer_ = pp::CompositorLayer();
2669f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    stable_texture_layer_ = pp::CompositorLayer();
2679f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    texture_layer_ = pp::CompositorLayer();
2689f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    image_layer_ = pp::CompositorLayer();
2699f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    frame = 0;
2709f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor    rebuild_layers_ = false;
2719f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor  }
2729f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor
273a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor  PrepareLayers(frame);
2749f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor
2759f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor  int32_t rv = compositor_.CommitLayers(
2769f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor      callback_factory_.NewCallback(&DemoInstance::Paint, ++frame));
2779f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor  assert(rv == PP_OK_COMPLETIONPENDING);
2789f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor
2799f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor  pp::VarDictionary dict;
2809f59234a91d057cee7c5e3cee91da8696858c692Douglas Gregor  dict.Set("total_resource", total_resource_);
281ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor  size_t free_resource = textures_.size() + images_.size();
282ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor  dict.Set("free_resource", static_cast<int32_t>(free_resource));
283ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor  PostMessage(dict);
284ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor}
285ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor
286ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregorvoid DemoInstance::PrepareLayers(int32_t frame) {
287dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor  int32_t rv;
288dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor  float factor_sin = sin(M_PI / 180 * frame);
289dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor  float factor_cos = cos(M_PI / 180 * frame);
290ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor  {
291699a07d8a0b1579c5178b3baf4bcf9edb6b38108Steve Naroff    // Set the background color layer.
292af08ddc8f1c53fed8d8d0ad82aa2a0bb7d654bd1Steve Naroff    if (color_layer_.is_null()) {
29389922f86f4e7da383af2a62ef04ad8b93b941220Steve Naroff      color_layer_ = compositor_.AddLayer();
294e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      assert(!color_layer_.is_null());
2951db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor      static const float transform[16] = {
29674844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek        1.0f, 0.0f, 0.0f, 0.0f,
2971db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor        0.0f, 1.0f, 0.0f, 0.0f,
298a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor        0.0f, 0.0f, 1.0f, 0.0f,
2991db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor        0.0f, 0.0f, 0.0f, 1.0f,
300e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      };
30174844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek      rv = color_layer_.SetTransform(transform);
30274844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek      assert(rv == PP_OK);
30374844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    }
30474844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek    rv = color_layer_.SetColor(fabs(factor_sin),
305e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek                               fabs(factor_cos),
30674844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek                               fabs(factor_sin * factor_cos),
30774844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek                               1.0f,
30874844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek                               pp::Size(800, 600));
3099298cfc7475c48fa42b168c37f628663d65ddde7Ted Kremenek    assert(rv == PP_OK);
3109298cfc7475c48fa42b168c37f628663d65ddde7Ted Kremenek  }
3110d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek
312ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek  {
313ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek    // Set the image layer
314ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek    if (image_layer_.is_null()) {
315ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek      image_layer_ = compositor_.AddLayer();
316ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek      assert(!image_layer_.is_null());
317a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    }
318a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    float x = frame % 800;
3195352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor    float y = 200 - 200 * factor_sin;
320274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor    const float transform[16] = {
3210a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      fabsf(factor_sin) + 0.2f, 0.0f, 0.0f, 0.0f,
322aa5f135f8db82b5e5fb1640fd51f8078e0b2d82dDouglas Gregor      0.0f, fabsf(factor_sin) + 0.2f, 0.0f, 0.0f,
323aa5f135f8db82b5e5fb1640fd51f8078e0b2d82dDouglas Gregor      0.0f, 0.0f, 1.0f, 0.0f,
3240a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor         x,    y, 0.0f, 1.0f,
325f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek    };
3260a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    rv = image_layer_.SetTransform(transform);
3275352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor    assert(rv == PP_OK);
328e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek
329274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor    pp::ImageData image = PrepareImage();
330274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor    uint8_t *p = static_cast<uint8_t*>(image.data());
331274f1906f12ebf8fcc179701deeda6d3271120c1Douglas Gregor    for (int x = 0; x < kImageWidth; ++x) {
332f7b714df46cdbdf9e2ebf26eb2fd7881790d83e6Ted Kremenek      for (int y = 0; y < kImageHeight; ++y) {
333a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor        *(p++) = frame;
334a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor        *(p++) = frame * x;
3350a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        *(p++) = frame * y;
3360a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor        *(p++) = 255;
337e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek      }
3380a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    }
3390a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    rv = image_layer_.SetImage(image, pp::Size(kImageWidth, kImageHeight),
340473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor        callback_factory_.NewCallback(&DemoInstance::OnImageReleased, image));
341473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    assert(rv == PP_OK_COMPLETIONPENDING);
342473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor  }
343473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor
344473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor  {
345473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    // Set the stable texture layer
346a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    if (stable_texture_layer_.is_null()) {
347a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor      stable_texture_layer_ = compositor_.AddLayer();
348a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor      assert(!stable_texture_layer_.is_null());
349473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      GLuint texture = PrepareFramebuffer();
350473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      cube_->UpdateForTimeDelta(0.02f);
351473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      cube_->Draw();
3520a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      rv = stable_texture_layer_.SetTexture(
353473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor          *context_,
354473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor          texture, pp::Size(600, 600),
355473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor          callback_factory_.NewCallback(&DemoInstance::OnTextureReleased,
3560a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor                                        texture));
3570a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      assert(rv == PP_OK_COMPLETIONPENDING);
3580a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      rv = stable_texture_layer_.SetPremultipliedAlpha(PP_FALSE);
3590a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      assert(rv == PP_OK);
360436f3f0400c633251e4071f81358c47bab964adfDouglas Gregor    }
361473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor
362473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    int32_t delta = 200 * fabsf(factor_sin);
3630a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    if (delta != 0) {
3640a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      int32_t x_y = 25 + delta;
3650a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      int32_t w_h =  650 - delta - delta;
366473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor      rv = stable_texture_layer_.SetClipRect(pp::Rect(x_y, x_y, w_h, w_h));
36751c6d384551674facc19f745ecf6e289d28dc55fDouglas Gregor    } else {
3680a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor      rv = stable_texture_layer_.SetClipRect(pp::Rect());
3690a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor    }
370473d7019bb54f8a2f0140dca9e9644a935cc6b20Douglas Gregor    assert(rv == PP_OK);
37151c6d384551674facc19f745ecf6e289d28dc55fDouglas Gregor
3725352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor    const float transform[16] = {
3735352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor      factor_cos, -factor_sin, 0.0f, 0.0f,
374a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      factor_sin, factor_cos, 0.0f, 0.0f,
375a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      0.0f, 0.0f, 1.0f, 0.0f,
376a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor      50.0f, 50.0f, 0.0f, 1.0f,
377a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    };
378a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    rv = stable_texture_layer_.SetTransform(transform);
379a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor    assert(rv == PP_OK);
380a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  }
381a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor
382a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor  {
38359fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    // Set the dynamic texture layer.
38459fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    if (texture_layer_.is_null()) {
3854e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek      texture_layer_ = compositor_.AddLayer();
386f787002478f09af1741fb0f82a562002e6799c49Ted Kremenek      assert(!texture_layer_.is_null());
3873c683367073e2d98a9046060f9bc7db872a1c63dFrancois Pichet      static const float transform[16] = {
3884e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek        1.0f, 0.0f, 0.0f, 0.0f,
389f787002478f09af1741fb0f82a562002e6799c49Ted Kremenek        0.0f, 1.0f, 0.0f, 0.0f,
39059fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek        0.0f, 0.0f, 1.0f, 0.0f,
39159fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek        200.0f, 0.0f, 0.0f, 1.0f,
3924e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek      };
39359fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek      rv = texture_layer_.SetTransform(transform);
39459fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek      assert(rv == PP_OK);
3954e6a3f7310d3d9232877ed6f439247b1054b1e47Ted Kremenek     }
39659fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek
397f787002478f09af1741fb0f82a562002e6799c49Ted Kremenek    GLuint texture = PrepareFramebuffer();
39859fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    cube_->UpdateForTimeDelta(0.02f);
39959fc1e55da9c856d1703d3d3ac14a36320d26b30Ted Kremenek    cube_->Draw();
400ce2ae88f834c740a28b7e074a4477039918f9bb0Ted Kremenek    rv = texture_layer_.SetTexture(*context_, texture, pp::Size(400, 400),
401e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor        callback_factory_.NewCallback(&DemoInstance::OnTextureReleased,
4020d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek                                      texture));
4030d435191fc8f78338c2ef26d566cfe4d2c52c706Ted Kremenek    assert(rv == PP_OK_COMPLETIONPENDING);
404fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek    rv = texture_layer_.SetPremultipliedAlpha(PP_FALSE);
405fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek    assert(rv == PP_OK);
406a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregor  }
407a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregor}
4081db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor
4091db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregorvoid DemoInstance::OnTextureReleased(int32_t result, GLuint texture) {
410e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek  if (result == PP_OK) {
411a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    textures_.push_back(texture);
412a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor  } else {
413a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    glDeleteTextures(1, &texture);
414a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor    total_resource_--;
4151db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor  }
41670ee54258035c860ebc71f7e5f803b74f3186889Ted Kremenek}
4171db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor
41851b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbarvoid DemoInstance::OnImageReleased(int32_t result, const pp::ImageData& image) {
41951b058cb1e726c49fe0fae29404a4ca4308a6a12Daniel Dunbar  if (result == PP_OK) {
420fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek    images_.push_back(image);
421fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek  } else {
422e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor    total_resource_--;
423e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  }
424e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor}
425e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor
426e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor// This object is the global object representing this plugin library as long
427fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek// as it is loaded.
428625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbarclass DemoModule : public pp::Module {
429e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek public:
430e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  DemoModule() : Module() {}
431e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  virtual ~DemoModule() {}
432e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor
433e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor  virtual pp::Instance* CreateInstance(PP_Instance instance) {
43498258afae66bab39b0c57a3efb6b20d4fbb5746cDouglas Gregor    return new DemoInstance(instance);
4351db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor  }
436a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor};
437fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek
4381db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor}  // anonymous namespace
439dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor
440a7bde20f8c6334ccc3a7ef4dd77243d0921a8497Douglas Gregornamespace pp {
441e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek// Factory function for your specialization of the Module object.
442e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas GregorModule* CreateModule() {
443625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar  return new DemoModule();
444e68fff6fc083c6270d835216a3de0b82c6ef0310Ted Kremenek}
445e5b72bac8312f83aeb2e29b3988ebfa30f2b4ca2Douglas Gregor}  // namespace pp
446625e4efc2c64b638285c9f836cc00a3ad7d0bd5fDaniel Dunbar