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)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdlib.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_video_capture_dev.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_opengles2.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/buffer_dev.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/device_ref_dev.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/video_capture_dev.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/video_capture_client_dev.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/completion_callback.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_3d_client.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_3d.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/lib/gl/include/GLES2/gl2.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When compiling natively on Windows, PostMessage can be #define-d to
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// something else.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PostMessage
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef PostMessage
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assert |context_| isn't holding any GL Errors.  Done as a macro instead of a
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function to preserve line number information in the failure message.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define AssertNoGLError() \
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_DCHECK(!gles2_if_->GetError(context_->pp_resource()));
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* const kDelimiter = "#__#";
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This object is the global object representing this plugin library as long
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it is loaded.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VCDemoModule : public pp::Module {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VCDemoModule() : pp::Module() {}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~VCDemoModule() {}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VCDemoInstance : public pp::Instance,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       public pp::Graphics3DClient,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       public pp::VideoCaptureClient_Dev {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VCDemoInstance(PP_Instance instance, pp::Module* module);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~VCDemoInstance();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pp::Instance implementation (see PPP_Instance).
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidChangeView(const pp::Rect& position,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const pp::Rect& clip_ignored);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void HandleMessage(const pp::Var& message_data);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pp::Graphics3DClient implementation.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Graphics3DContextLost() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitGL();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateYUVTextures();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Render();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDeviceInfo(PP_Resource resource,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const PP_VideoCaptureDeviceInfo_Dev& info,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::vector<pp::Buffer_Dev>& buffers) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_info_ = info;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffers_ = buffers;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateYUVTextures();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnStatus(PP_Resource resource, uint32_t status) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnError(PP_Resource resource, uint32_t error) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnBufferReady(PP_Resource resource, uint32_t buffer) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data = static_cast<const char*>(buffers_[buffer].data());
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t width = capture_info_.width;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t height = capture_info_.height;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->TexSubImage2D(
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data += width * height;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width /= 2;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height /= 2;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->TexSubImage2D(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data += width * height;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->TexSubImage2D(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    video_capture_.ReuseBuffer(buffer);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_painting_)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      needs_paint_ = true;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Render();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Render();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GL-related functions.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitGL();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint CreateTexture(int32_t width, int32_t height, int unit);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateGLObjects();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateShader(GLuint program, GLenum type, const char* source, int size);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PaintFinished(int32_t result);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateYUVTextures();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Open(const pp::DeviceRef_Dev& device);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Stop();
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Start();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EnumerateDevicesFinished(int32_t result,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                std::vector<pp::DeviceRef_Dev>& devices);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenFinished(int32_t result);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void MonitorDeviceChangeCallback(void* user_data,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          uint32_t device_count,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const PP_Resource devices[]);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Size position_size_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_painting_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool needs_paint_;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint texture_y_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint texture_u_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint texture_v_;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::VideoCapture_Dev video_capture_;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_VideoCaptureDeviceInfo_Dev capture_info_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<pp::Buffer_Dev> buffers_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallbackFactory<VCDemoInstance> callback_factory_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unowned pointers.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const struct PPB_OpenGLES2* gles2_if_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owned data.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Graphics3D* context_;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<pp::DeviceRef_Dev> enumerate_devices_;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<pp::DeviceRef_Dev> monitor_devices_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VCDemoInstance::VCDemoInstance(PP_Instance instance, pp::Module* module)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pp::Instance(instance),
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Graphics3DClient(this),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::VideoCaptureClient_Dev(this),
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_painting_(false),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      needs_paint_(false),
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      texture_y_(0),
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      texture_u_(0),
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      texture_v_(0),
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      video_capture_(this),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_factory_(this),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_(NULL) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_ = static_cast<const struct PPB_OpenGLES2*>(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE));
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_DCHECK(gles2_if_);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_info_.width = 320;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_info_.height = 240;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_info_.frames_per_second = 30;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VCDemoInstance::~VCDemoInstance() {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_capture_.MonitorDeviceChange(NULL, NULL);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete context_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::DidChangeView(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const pp::Rect& position, const pp::Rect& clip_ignored) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position.width() == 0 || position.height() == 0)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (position.size() == position_size_)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position_size_ = position.size();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize graphics.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitGL();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Render();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::HandleMessage(const pp::Var& message_data) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_data.is_string()) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string event = message_data.AsString();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event == "PageInitialized") {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int32_t result = video_capture_.MonitorDeviceChange(
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &VCDemoInstance::MonitorDeviceChangeCallback, this);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (result != PP_OK)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        PostMessage(pp::Var("MonitorDeviceChangeFailed"));
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::CompletionCallbackWithOutput<std::vector<pp::DeviceRef_Dev> >
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          callback = callback_factory_.NewCallbackWithOutput(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &VCDemoInstance::EnumerateDevicesFinished);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result = video_capture_.EnumerateDevices(callback);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (result != PP_OK_COMPLETIONPENDING)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        PostMessage(pp::Var("EnumerationFailed"));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (event == "UseDefault") {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Open(pp::DeviceRef_Dev());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (event == "Stop") {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Stop();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (event == "Start") {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Start();
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (event.find("Monitor:") == 0) {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string index_str = event.substr(strlen("Monitor:"));
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int index = atoi(index_str.c_str());
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (index >= 0 && index < static_cast<int>(monitor_devices_.size()))
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Open(monitor_devices_[index]);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        PP_NOTREACHED();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (event.find("Enumerate:") == 0) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string index_str = event.substr(strlen("Enumerate:"));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int index = atoi(index_str.c_str());
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (index >= 0 && index < static_cast<int>(enumerate_devices_.size()))
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Open(enumerate_devices_[index]);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        PP_NOTREACHED();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::InitGL() {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_DCHECK(position_size_.width() && position_size_.height());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_painting_ = false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete context_;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t attributes[] = {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 0,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_SAMPLES, 0,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_WIDTH, position_size_.width(),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_HEIGHT, position_size_.height(),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GRAPHICS3DATTRIB_NONE,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = new pp::Graphics3D(this, attributes);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_DCHECK(!context_->is_null());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set viewport window size and clear color bit.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ClearColor(context_->pp_resource(), 1, 0, 0, 1);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Viewport(context_->pp_resource(), 0, 0,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      position_size_.width(), position_size_.height());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BindGraphics(*context_);
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateGLObjects();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::Render() {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_DCHECK(!is_painting_);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_painting_ = true;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  needs_paint_ = false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (texture_y_) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallback cb = callback_factory_.NewCallback(
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &VCDemoInstance::PaintFinished);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_->SwapBuffers(cb);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::PaintFinished(int32_t result) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_painting_ = false;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (needs_paint_)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Render();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint VCDemoInstance::CreateTexture(int32_t width, int32_t height, int unit) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint texture_id;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign parameters.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0 + unit);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameteri(
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_NEAREST);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameteri(
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_NEAREST);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameterf(
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_CLAMP_TO_EDGE);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexParameterf(
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_CLAMP_TO_EDGE);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate texture.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->TexImage2D(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->pp_resource(), GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return texture_id;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::CreateGLObjects() {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Code and constants for shader.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kVertexShader[] =
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "varying vec2 v_texCoord;            \n"
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "attribute vec4 a_position;          \n"
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "attribute vec2 a_texCoord;          \n"
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void main()                         \n"
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{                                   \n"
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    v_texCoord = a_texCoord;        \n"
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    gl_Position = a_position;       \n"
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kFragmentShader[] =
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "precision mediump float;                                   \n"
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "varying vec2 v_texCoord;                                   \n"
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "uniform sampler2D y_texture;                               \n"
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "uniform sampler2D u_texture;                               \n"
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "uniform sampler2D v_texture;                               \n"
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "uniform mat3 color_matrix;                                 \n"
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void main()                                                \n"
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{                                                          \n"
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  vec3 yuv;                                                \n"
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  yuv.x = texture2D(y_texture, v_texCoord).r;              \n"
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  yuv.y = texture2D(u_texture, v_texCoord).r;              \n"
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  yuv.z = texture2D(v_texture, v_texCoord).r;              \n"
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  vec3 rgb = color_matrix * (yuv - vec3(0.0625, 0.5, 0.5));\n"
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  gl_FragColor = vec4(rgb, 1.0);                           \n"
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const float kColorMatrix[9] = {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1.1643828125f, 1.1643828125f, 1.1643828125f,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0.0f, -0.39176171875f, 2.017234375f,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1.59602734375f, -0.81296875f, 0.0f
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource context = context_->pp_resource();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create shader program.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint program = gles2_if_->CreateProgram(context);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateShader(program, GL_VERTEX_SHADER, kVertexShader, sizeof(kVertexShader));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateShader(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      program, GL_FRAGMENT_SHADER, kFragmentShader, sizeof(kFragmentShader));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->LinkProgram(context, program);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->UseProgram(context, program);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->DeleteProgram(context, program);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Uniform1i(
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context, gles2_if_->GetUniformLocation(context, program, "y_texture"), 0);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Uniform1i(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context, gles2_if_->GetUniformLocation(context, program, "u_texture"), 1);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->Uniform1i(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context, gles2_if_->GetUniformLocation(context, program, "v_texture"), 2);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->UniformMatrix3fv(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gles2_if_->GetUniformLocation(context, program, "color_matrix"),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1, GL_FALSE, kColorMatrix);
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign vertex positions and texture coordinates to buffers for use in
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shader program.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const float kVertices[] = {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    -1, 1, -1, -1, 1, 1, 1, -1,  // Position coordinates.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 0, 0, 1, 1, 0, 1, 1,  // Texture coordinates.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint buffer;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->GenBuffers(context, 1, &buffer);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BindBuffer(context, GL_ARRAY_BUFFER, buffer);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->BufferData(context, GL_ARRAY_BUFFER,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(kVertices), kVertices, GL_STATIC_DRAW);
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint pos_location = gles2_if_->GetAttribLocation(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context, program, "a_position");
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint tc_location = gles2_if_->GetAttribLocation(
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context, program, "a_texCoord");
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->EnableVertexAttribArray(context, pos_location);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->VertexAttribPointer(context, pos_location, 2,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GL_FLOAT, GL_FALSE, 0, 0);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->EnableVertexAttribArray(context, tc_location);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->VertexAttribPointer(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context, tc_location, 2, GL_FLOAT, GL_FALSE, 0,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<float*>(0) + 8);  // Skip position coordinates.
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertNoGLError();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::CreateShader(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLuint program, GLenum type, const char* source, int size) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource context = context_->pp_resource();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint shader = gles2_if_->CreateShader(context, type);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->ShaderSource(context, shader, 1, &source, &size);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->CompileShader(context, shader);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->AttachShader(context, program, shader);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gles2_if_->DeleteShader(context, shader);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::CreateYUVTextures() {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t width = capture_info_.width;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t height = capture_info_.height;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  texture_y_ = CreateTexture(width, height, 0);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width /= 2;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height /= 2;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  texture_u_ = CreateTexture(width, height, 1);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  texture_v_ = CreateTexture(width, height, 2);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::Open(const pp::DeviceRef_Dev& device) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallback callback = callback_factory_.NewCallback(
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &VCDemoInstance::OpenFinished);
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t result = video_capture_.Open(device, capture_info_, 4, callback);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result != PP_OK_COMPLETIONPENDING)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostMessage(pp::Var("OpenFailed"));
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VCDemoInstance::Stop() {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (video_capture_.StopCapture() != PP_OK)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostMessage(pp::Var("StopFailed"));
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VCDemoInstance::Start() {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (video_capture_.StartCapture() != PP_OK)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostMessage(pp::Var("StartFailed"));
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::EnumerateDevicesFinished(
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<pp::DeviceRef_Dev>& devices) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == PP_OK) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enumerate_devices_.swap(devices);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string device_names = "Enumerate:";
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t index = 0; index < enumerate_devices_.size(); ++index) {
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pp::Var name = enumerate_devices_[index].GetName();
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PP_DCHECK(name.is_string());
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index != 0)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device_names += kDelimiter;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_names += name.AsString();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostMessage(pp::Var(device_names));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostMessage(pp::Var("EnumerationFailed"));
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VCDemoInstance::OpenFinished(int32_t result) {
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result == PP_OK)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Start();
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostMessage(pp::Var("OpenFailed"));
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VCDemoInstance::MonitorDeviceChangeCallback(void* user_data,
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 uint32_t device_count,
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 const PP_Resource devices[]) {
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VCDemoInstance* thiz = static_cast<VCDemoInstance*>(user_data);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string device_names = "Monitor:";
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thiz->monitor_devices_.clear();
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thiz->monitor_devices_.reserve(device_count);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t index = 0; index < device_count; ++index) {
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thiz->monitor_devices_.push_back(pp::DeviceRef_Dev(devices[index]));
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pp::Var name = thiz->monitor_devices_.back().GetName();
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PP_DCHECK(name.is_string());
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (index != 0)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      device_names += kDelimiter;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    device_names += name.AsString();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thiz->PostMessage(pp::Var(device_names));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pp::Instance* VCDemoModule::CreateInstance(PP_Instance instance) {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new VCDemoInstance(instance, this);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory function for your specialization of the Module object.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Module* CreateModule() {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new VCDemoModule();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
505