15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <sstream>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/ppb_console.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_opengles2.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/video_decoder_client_dev.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/video_decoder_dev.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_3d.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_3d_client.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/rect.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/examples/video_decode/testdata.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/lib/gl/include/GLES2/gl2.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/lib/gl/include/GLES2/gl2ext.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use assert as a poor-man's CHECK, even in non-debug mode.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since <assert.h> redefines assert on every inclusion (it doesn't use
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// include-guards), make sure this is the last file #include'd in this file.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef NDEBUG
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assert |context_| isn't holding any GL Errors.  Done as a macro instead of a
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function to preserve line number information in the failure message.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define assertNoGLError() \
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(!gles2_if_->GetError(context_->pp_resource()));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PictureBufferInfo {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_PictureBuffer_Dev buffer;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLenum texture_target;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Shader {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shader() : program(0),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             texcoord_scale_location(0) {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint program;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint texcoord_scale_location;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoDecodeDemoInstance : public pp::Instance,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                public pp::Graphics3DClient,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                public pp::VideoDecoderClient_Dev {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoDecodeDemoInstance(PP_Instance instance, pp::Module* module);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~VideoDecodeDemoInstance();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pp::Instance implementation (see PPP_Instance).
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidChangeView(const pp::Rect& position,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const pp::Rect& clip_ignored);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pp::Graphics3DClient implementation.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Graphics3DContextLost() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(vrk/fischman): Properly reset after a lost graphics context.  In
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // particular need to delete context_ and re-create textures.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Probably have to recreate the decoder from scratch, because old textures
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can still be outstanding in the decoder!
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    assert(false && "Unexpectedly lost graphics context");
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pp::VideoDecoderClient_Dev implementation.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ProvidePictureBuffers(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_Resource decoder,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32_t req_num_of_bufs,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const PP_Size& dimensions,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32_t texture_target);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DismissPictureBuffer(PP_Resource decoder,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int32_t picture_buffer_id);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void PictureReady(PP_Resource decoder, const PP_Picture_Dev& picture);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void NotifyError(PP_Resource decoder, PP_VideoDecodeError_Dev error);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum { kNumConcurrentDecodes = 7,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         kNumDecoders = 2 };  // Baked into viewport rendering.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A single decoder's client interface.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DecoderClient {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecoderClient(VideoDecodeDemoInstance* gles2,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  pp::VideoDecoder_Dev* decoder);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~DecoderClient();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void DecodeNextNALUs();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Per-decoder implementation of part of pp::VideoDecoderClient_Dev.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void ProvidePictureBuffers(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t req_num_of_bufs,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_Size dimensions,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t texture_target);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void DismissPictureBuffer(int32_t picture_buffer_id);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PictureBufferInfo& GetPictureBufferInfoById(int id);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::VideoDecoder_Dev* decoder() { return decoder_; }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void DecodeNextNALU();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static void GetNextNALUBoundary(size_t start_pos, size_t* end_pos);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void DecoderBitstreamDone(int32_t result, int bitstream_buffer_id);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void DecoderFlushDone(int32_t result);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoDecodeDemoInstance* gles2_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::VideoDecoder_Dev* decoder_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::CompletionCallbackFactory<DecoderClient> callback_factory_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int next_picture_buffer_id_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int next_bitstream_buffer_id_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t encoded_data_next_pos_to_decode_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<int> bitstream_ids_at_decoder_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Map of texture buffers indexed by buffer id.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::map<int, PictureBufferInfo> PictureBufferMap;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PictureBufferMap picture_buffers_by_id_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Map of bitstream buffers indexed by id.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::map<int, pp::Buffer_Dev*> BitstreamBufferMap;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BitstreamBufferMap bitstream_buffers_by_id_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize Video Decoders.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitializeDecoders();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GL-related functions.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitGL();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint CreateTexture(int32_t width, int32_t height, GLenum texture_target);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateGLObjects();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Create2DProgramOnce();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateRectangleARBProgramOnce();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shader CreateProgram(const char* vertex_shader,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* fragment_shader);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateShader(GLuint program, GLenum type, const char* source, int size);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteTexture(GLuint id);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PaintFinished(int32_t result, PP_Resource decoder,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int picture_buffer_id);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log an error to the developer console and stderr (though the latter may be
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // closed due to sandboxing or blackholed for other reasons) by creating a
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // temporary of this type and streaming to it.  Example usage:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LogError(this).s() << "Hello world: " << 42;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class LogError {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogError(VideoDecodeDemoInstance* demo) : demo_(demo) {}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~LogError() {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& msg = stream_.str();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      demo_->console_if_->Log(demo_->pp_instance(), PP_LOGLEVEL_ERROR,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              pp::Var(msg).pp_var());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::cerr << msg << std::endl;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Impl note: it would have been nicer to have LogError derive from
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // std::ostringstream so that it can be streamed to directly, but lookup
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // rules turn streamed string literals to hex pointers on output.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::ostringstream& s() { return stream_; }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoDecodeDemoInstance* demo_;  // Unowned.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::ostringstream stream_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Size plugin_size_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_painting_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When decode outpaces render, we queue up decoded pictures for later
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // painting.  Elements are <decoder,picture>.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<std::pair<PP_Resource, PP_Picture_Dev> > pictures_pending_paint_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_frames_rendered_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_TimeTicks first_frame_delivered_ticks_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_TimeTicks last_swap_request_ticks_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_TimeTicks swap_ticks_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallbackFactory<VideoDecodeDemoInstance> callback_factory_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unowned pointers.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const PPB_Console* console_if_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Core* core_if_;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_OpenGLES2* gles2_if_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owned data.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Graphics3D* context_;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<int, DecoderClient*> Decoders;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Decoders video_decoders_;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shader program to draw GL_TEXTURE_2D target.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shader shader_2d_;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shader shader_rectangle_arb_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoDecodeDemoInstance::DecoderClient::DecoderClient(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoDecodeDemoInstance* gles2, pp::VideoDecoder_Dev* decoder)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : gles2_(gles2), decoder_(decoder), callback_factory_(this),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_picture_buffer_id_(0),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_bitstream_buffer_id_(0), encoded_data_next_pos_to_decode_(0) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoDecodeDemoInstance::DecoderClient::~DecoderClient() {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete decoder_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_ = NULL;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (BitstreamBufferMap::iterator it = bitstream_buffers_by_id_.begin();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != bitstream_buffers_by_id_.end(); ++it) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffers_by_id_.clear();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PictureBufferMap::iterator it = picture_buffers_by_id_.begin();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != picture_buffers_by_id_.end(); ++it) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_->DeleteTexture(it->second.buffer.texture_id);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  picture_buffers_by_id_.clear();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoDecodeDemoInstance::VideoDecodeDemoInstance(PP_Instance instance,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 pp::Module* module)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pp::Instance(instance), pp::Graphics3DClient(this),
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::VideoDecoderClient_Dev(this),
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      is_painting_(false),
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_frames_rendered_(0),
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_frame_delivered_ticks_(-1),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      swap_ticks_(0),
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_factory_(this),
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      console_if_(static_cast<const PPB_Console*>(
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          module->GetBrowserInterface(PPB_CONSOLE_INTERFACE))),
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      core_if_(static_cast<const PPB_Core*>(
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          module->GetBrowserInterface(PPB_CORE_INTERFACE))),
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      gles2_if_(static_cast<const PPB_OpenGLES2*>(
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE))),
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_(NULL) {
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  assert(console_if_);
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  assert(core_if_);
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  assert(gles2_if_);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoDecodeDemoInstance::~VideoDecodeDemoInstance() {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shader_2d_.program)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->DeleteProgram(context_->pp_resource(), shader_2d_.program);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shader_rectangle_arb_.program) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->DeleteProgram(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), shader_rectangle_arb_.program);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Decoders::iterator it = video_decoders_.begin();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != video_decoders_.end(); ++it) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decoders_.clear();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete context_;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DidChangeView(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const pp::Rect& position, const pp::Rect& clip_ignored) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position.width() == 0 || position.height() == 0)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (plugin_size_.width()) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(position.size() == plugin_size_);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugin_size_ = position.size();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize graphics.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitGL();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeDecoders();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::InitializeDecoders() {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(video_decoders_.empty());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumDecoders; ++i) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecoderClient* client = new DecoderClient(
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this, new pp::VideoDecoder_Dev(
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            this, *context_, PP_VIDEODECODER_H264PROFILE_MAIN));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(!client->decoder()->is_null());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(video_decoders_.insert(std::make_pair(
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        client->decoder()->pp_resource(), client)).second);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client->DecodeNextNALUs();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::DecoderBitstreamDone(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result, int bitstream_buffer_id) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(bitstream_ids_at_decoder_.erase(bitstream_buffer_id) == 1);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BitstreamBufferMap::iterator it =
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitstream_buffers_by_id_.find(bitstream_buffer_id);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(it != bitstream_buffers_by_id_.end());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete it->second;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffers_by_id_.erase(it);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecodeNextNALUs();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::DecoderFlushDone(int32_t result) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(result == PP_OK);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that each bitstream buffer ID we handed to the decoder got handed
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back to us.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(bitstream_ids_at_decoder_.empty());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete decoder_;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_ = NULL;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool LookingAtNAL(const unsigned char* encoded, size_t pos) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pos + 3 < kDataLen &&
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encoded[pos] == 0 && encoded[pos + 1] == 0 &&
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encoded[pos + 2] == 0 && encoded[pos + 3] == 1;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::GetNextNALUBoundary(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t start_pos, size_t* end_pos) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(LookingAtNAL(kData, start_pos));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *end_pos = start_pos;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *end_pos += 4;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*end_pos + 3 < kDataLen &&
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !LookingAtNAL(kData, *end_pos)) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++*end_pos;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*end_pos + 3 >= kDataLen) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *end_pos = kDataLen;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::DecodeNextNALUs() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (encoded_data_next_pos_to_decode_ <= kDataLen &&
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         bitstream_ids_at_decoder_.size() < kNumConcurrentDecodes) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecodeNextNALU();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::DecodeNextNALU() {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (encoded_data_next_pos_to_decode_ == kDataLen) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++encoded_data_next_pos_to_decode_;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::CompletionCallback cb = callback_factory_.NewCallback(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &VideoDecodeDemoInstance::DecoderClient::DecoderFlushDone);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decoder_->Flush(cb);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t start_pos = encoded_data_next_pos_to_decode_;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t end_pos;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetNextNALUBoundary(start_pos, &end_pos);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Buffer_Dev* buffer = new pp::Buffer_Dev(gles2_, end_pos - start_pos);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_VideoBitstreamBuffer_Dev bitstream_buffer;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int id = ++next_bitstream_buffer_id_;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffer.id = id;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffer.size = end_pos - start_pos;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffer.data = buffer->pp_resource();
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer->data(), kData + start_pos, end_pos - start_pos);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(bitstream_buffers_by_id_.insert(std::make_pair(id, buffer)).second);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallback cb =
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_factory_.NewCallback(
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &VideoDecodeDemoInstance::DecoderClient::DecoderBitstreamDone, id);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(bitstream_ids_at_decoder_.insert(id).second);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoded_data_next_pos_to_decode_ = end_pos;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_->Decode(bitstream_buffer, cb);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::ProvidePictureBuffers(PP_Resource decoder,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    uint32_t req_num_of_bufs,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    const PP_Size& dimensions,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    uint32_t texture_target) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecoderClient* client = video_decoders_[decoder];
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(client);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->ProvidePictureBuffers(req_num_of_bufs, dimensions, texture_target);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::ProvidePictureBuffers(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t req_num_of_bufs,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Size dimensions,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t texture_target) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PP_PictureBuffer_Dev> buffers;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < req_num_of_bufs; ++i) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PictureBufferInfo info;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.buffer.size = dimensions;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.texture_target = texture_target;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.buffer.texture_id = gles2_->CreateTexture(
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dimensions.width, dimensions.height, info.texture_target);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id = ++next_picture_buffer_id_;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.buffer.id = id;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffers.push_back(info.buffer);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(picture_buffers_by_id_.insert(std::make_pair(id, info)).second);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_->AssignPictureBuffers(buffers);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PictureBufferInfo&
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoDecodeDemoInstance::DecoderClient::GetPictureBufferInfoById(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PictureBufferMap::iterator it = picture_buffers_by_id_.find(id);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(it != picture_buffers_by_id_.end());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it->second;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DismissPictureBuffer(PP_Resource decoder,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             int32_t picture_buffer_id) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecoderClient* client = video_decoders_[decoder];
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(client);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->DismissPictureBuffer(picture_buffer_id);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DecoderClient::DismissPictureBuffer(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t picture_buffer_id) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_->DeleteTexture(GetPictureBufferInfoById(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      picture_buffer_id).buffer.texture_id);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  picture_buffers_by_id_.erase(picture_buffer_id);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::PictureReady(PP_Resource decoder,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const PP_Picture_Dev& picture) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_frame_delivered_ticks_ == -1)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert((first_frame_delivered_ticks_ = core_if_->GetTimeTicks()) != -1);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_painting_) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pictures_pending_paint_.push_back(std::make_pair(decoder, picture));
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecoderClient* client = video_decoders_[decoder];
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(client);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PictureBufferInfo& info =
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client->GetPictureBufferInfoById(picture.picture_buffer_id);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(!is_painting_);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_painting_ = true;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x = 0;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y = 0;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client != video_decoders_.begin()->second) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = plugin_size_.width() / kNumDecoders;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y = plugin_size_.height() / kNumDecoders;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info.texture_target == GL_TEXTURE_2D) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Create2DProgramOnce();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->UseProgram(context_->pp_resource(), shader_2d_.program);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->Uniform2f(
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), shader_2d_.texcoord_scale_location, 1.0, 1.0);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(info.texture_target == GL_TEXTURE_RECTANGLE_ARB);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateRectangleARBProgramOnce();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->UseProgram(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), shader_rectangle_arb_.program);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->Uniform2f(context_->pp_resource(),
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         shader_rectangle_arb_.texcoord_scale_location,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         info.buffer.size.width,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         info.buffer.size.height);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Viewport(context_->pp_resource(), x, y,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      plugin_size_.width() / kNumDecoders,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      plugin_size_.height() / kNumDecoders);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BindTexture(
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), info.texture_target, info.buffer.texture_id);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->UseProgram(context_->pp_resource(), 0);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallback cb =
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_factory_.NewCallback(
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &VideoDecodeDemoInstance::PaintFinished, decoder, info.buffer.id);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_swap_request_ticks_ = core_if_->GetTimeTicks();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(context_->SwapBuffers(cb) == PP_OK_COMPLETIONPENDING);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::NotifyError(PP_Resource decoder,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          PP_VideoDecodeError_Dev error) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogError(this).s() << "Received error: " << error;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(false && "Unexpected error; see stderr for details");
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This object is the global object representing this plugin library as long
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it is loaded.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoDecodeDemoModule : public pp::Module {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoDecodeDemoModule() : pp::Module() {}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~VideoDecodeDemoModule() {}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new VideoDecodeDemoInstance(instance, this);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::InitGL() {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(plugin_size_.width() && plugin_size_.height());
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_painting_ = false;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(!context_);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t context_attributes[] = {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_SAMPLES, 0,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(),
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(),
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_NONE,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = new pp::Graphics3D(this, context_attributes);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(!context_->is_null());
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(BindGraphics(*context_));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear color bit.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ClearColor(context_->pp_resource(), 1, 0, 0, 1);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateGLObjects();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::PaintFinished(int32_t result, PP_Resource decoder,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int picture_buffer_id) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(result == PP_OK);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  swap_ticks_ += core_if_->GetTimeTicks() - last_swap_request_ticks_;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_painting_ = false;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_frames_rendered_;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_frames_rendered_ % 50 == 0) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogError(this).s() << "Rendered frames: " << num_frames_rendered_
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       << ", fps: " << fps << ", with average ms/swap of: "
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       << ms_per_swap;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecoderClient* client = video_decoders_[decoder];
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client && client->decoder())
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client->decoder()->ReusePictureBuffer(picture_buffer_id);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pictures_pending_paint_.empty()) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::pair<PP_Resource, PP_Picture_Dev> decoder_picture =
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pictures_pending_paint_.front();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pictures_pending_paint_.pop_front();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PictureReady(decoder_picture.first, decoder_picture.second);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint VideoDecodeDemoInstance::CreateTexture(int32_t width,
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int32_t height,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              GLenum texture_target) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint texture_id;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign parameters.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BindTexture(context_->pp_resource(), texture_target, texture_id);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameteri(
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), texture_target, GL_TEXTURE_MIN_FILTER,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_NEAREST);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameteri(
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), texture_target, GL_TEXTURE_MAG_FILTER,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_NEAREST);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameterf(
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), texture_target, GL_TEXTURE_WRAP_S,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_CLAMP_TO_EDGE);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameterf(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), texture_target, GL_TEXTURE_WRAP_T,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_CLAMP_TO_EDGE);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (texture_target == GL_TEXTURE_2D) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->TexImage2D(
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), texture_target, 0, GL_RGBA, width, height, 0,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_RGBA, GL_UNSIGNED_BYTE, NULL);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return texture_id;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::DeleteTexture(GLuint id) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->DeleteTextures(context_->pp_resource(), 1, &id);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::CreateGLObjects() {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign vertex positions and texture coordinates to buffers for use in
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shader program.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const float kVertices[] = {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    -1, 1, -1, -1, 1, 1, 1, -1,  // Position coordinates.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0, 0, 1, 1, 1, 0,      // Texture coordinates.
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint buffer;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BufferData(context_->pp_resource(), GL_ARRAY_BUFFER,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(kVertices), kVertices, GL_STATIC_DRAW);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kVertexShader[] =
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "varying vec2 v_texCoord;            \n"
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "attribute vec4 a_position;          \n"
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "attribute vec2 a_texCoord;          \n"
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "uniform vec2 v_scale;               \n"
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void main()                         \n"
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{                                   \n"
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    v_texCoord = v_scale * a_texCoord; \n"
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    gl_Position = a_position;       \n"
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}";
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::Create2DProgramOnce() {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shader_2d_.program)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kFragmentShader2D[] =
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "precision mediump float;            \n"
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "varying vec2 v_texCoord;            \n"
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "uniform sampler2D s_texture;        \n"
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void main()                         \n"
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{"
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    gl_FragColor = texture2D(s_texture, v_texCoord); \n"
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shader_2d_ = CreateProgram(kVertexShader, kFragmentShader2D);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::CreateRectangleARBProgramOnce() {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shader_rectangle_arb_.program)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kFragmentShaderRectangle[] =
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "#extension GL_ARB_texture_rectangle : require\n"
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "precision mediump float;            \n"
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "varying vec2 v_texCoord;            \n"
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "uniform sampler2DRect s_texture;    \n"
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void main()                         \n"
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{"
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    gl_FragColor = texture2DRect(s_texture, v_texCoord).rgba; \n"
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shader_rectangle_arb_ =
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateProgram(kVertexShader, kFragmentShaderRectangle);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Shader VideoDecodeDemoInstance::CreateProgram(const char* vertex_shader,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const char* fragment_shader) {
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shader shader;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create shader program.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shader.program = gles2_if_->CreateProgram(context_->pp_resource());
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateShader(shader.program, GL_VERTEX_SHADER, vertex_shader,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               strlen(vertex_shader));
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateShader(shader.program, GL_FRAGMENT_SHADER, fragment_shader,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               strlen(fragment_shader));
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->LinkProgram(context_->pp_resource(), shader.program);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->UseProgram(context_->pp_resource(), shader.program);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Uniform1i(
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(),
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gles2_if_->GetUniformLocation(
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          context_->pp_resource(), shader.program, "s_texture"), 0);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shader.texcoord_scale_location = gles2_if_->GetUniformLocation(
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), shader.program, "v_scale");
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint pos_location = gles2_if_->GetAttribLocation(
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), shader.program, "a_position");
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint tc_location = gles2_if_->GetAttribLocation(
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), shader.program, "a_texCoord");
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->EnableVertexAttribArray(context_->pp_resource(), pos_location);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->VertexAttribPointer(context_->pp_resource(), pos_location, 2,
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GL_FLOAT, GL_FALSE, 0, 0);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->EnableVertexAttribArray(context_->pp_resource(), tc_location);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->VertexAttribPointer(
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), tc_location, 2, GL_FLOAT, GL_FALSE, 0,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<float*>(0) + 8);  // Skip position coordinates.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->UseProgram(context_->pp_resource(), 0);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assertNoGLError();
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shader;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoDecodeDemoInstance::CreateShader(
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLuint program, GLenum type, const char* source, int size) {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint shader = gles2_if_->CreateShader(context_->pp_resource(), type);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ShaderSource(context_->pp_resource(), shader, 1, &source, &size);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->CompileShader(context_->pp_resource(), shader);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->AttachShader(context_->pp_resource(), program, shader);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->DeleteShader(context_->pp_resource(), shader);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory function for your specialization of the Module object.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Module* CreateModule() {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new VideoDecodeDemoModule();
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
689