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 "content/common/gpu/image_transport_surface.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_cftyperef.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "content/common/gpu/gpu_command_buffer_stub.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/native_widget_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_cgl.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/gl_surface_osmesa.h"
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gl/io_surface_support_mac.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IOSurface dimensions will be rounded up to a multiple of this value in order
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to reduce memory thrashing during resize. This must be a power of 2.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kIOSurfaceDimensionRoundup = 64;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int RoundUpSurfaceDimension(int number) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(number >= 0);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cast into unsigned space for portable bitwise ops.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 unsigned_number = static_cast<uint32>(number);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 roundup_sub_1 = kIOSurfaceDimensionRoundup - 1;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned_number = (unsigned_number + roundup_sub_1) & ~roundup_sub_1;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(unsigned_number);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We are backed by an offscreen surface for the purposes of creating
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a context, but use FBOs to render to texture backed IOSurface
375e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)class IOSurfaceImageTransportSurface
385e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    : public gfx::NoOpGLSurfaceCGL,
395e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      public ImageTransportSurface,
405e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      public GpuCommandBufferStub::DestructionObserver {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOSurfaceImageTransportSurface(GpuChannelManager* manager,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GpuCommandBufferStub* stub,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 gfx::PluginWindowHandle handle);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GLSurface implementation
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Initialize() OVERRIDE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Destroy() OVERRIDE;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool DeferDraws() OVERRIDE;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsOffscreen() OVERRIDE;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool SwapBuffers() OVERRIDE;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string GetExtensions() OVERRIDE;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual gfx::Size GetSize() OVERRIDE;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SetBackbufferAllocation(bool allocated) OVERRIDE;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ImageTransportSurface implementation
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnBufferPresented(
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnResizeViewACK() OVERRIDE;
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void SetLatencyInfo(const ui::LatencyInfo&) OVERRIDE;
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void WakeUpGpu() OVERRIDE;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // GpuCommandBufferStub::DestructionObserver implementation.
705e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  virtual void OnWillDestroyStub() OVERRIDE;
715e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~IOSurfaceImageTransportSurface() OVERRIDE;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AdjustBufferAllocation();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnrefIOSurface();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateIOSurface();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tracks the current buffer allocation state.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool backbuffer_suggested_allocation_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool frontbuffer_suggested_allocation_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 fbo_id_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint texture_id_;
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GLuint depth_stencil_renderbuffer_id_;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFTypeRef> io_surface_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The id of |io_surface_| or 0 if that's NULL.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 io_surface_handle_;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Weak pointer to the context that this was last made current to.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::GLContext* context_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size size_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size rounded_size_;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  float scale_factor_;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether or not we've successfully made the surface current once.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool made_current_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether a SwapBuffers is pending.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_swap_buffers_pending_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether we unscheduled command buffer because of pending SwapBuffers.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_unschedule_;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ui::LatencyInfo latency_info_;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ImageTransportHelper> helper_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(IOSurfaceImageTransportSurface);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddBooleanValue(CFMutableDictionaryRef dictionary,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const CFStringRef key,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     bool value) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFDictionaryAddValue(dictionary, key,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       (value ? kCFBooleanTrue : kCFBooleanFalse));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddIntegerValue(CFMutableDictionaryRef dictionary,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const CFStringRef key,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int32 value) {
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFNumberRef> number(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFDictionaryAddValue(dictionary, key, number.get());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOSurfaceImageTransportSurface::IOSurfaceImageTransportSurface(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelManager* manager,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuCommandBufferStub* stub,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::PluginWindowHandle handle)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : gfx::NoOpGLSurfaceCGL(gfx::Size(1, 1)),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backbuffer_suggested_allocation_(true),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frontbuffer_suggested_allocation_(true),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fbo_id_(0),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      texture_id_(0),
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      depth_stencil_renderbuffer_id_(0),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_surface_handle_(0),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_(NULL),
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      scale_factor_(1.f),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      made_current_(false),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_swap_buffers_pending_(false),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      did_unschedule_(false) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOSurfaceImageTransportSurface::~IOSurfaceImageTransportSurface() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IOSurfaceImageTransportSurface::Initialize() {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only support IOSurfaces if the GL implementation is the native desktop GL.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO surfaces will not work with, for example, OSMesa software renderer
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GL contexts.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!helper_->Initialize())
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1625e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1635e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (!NoOpGLSurfaceCGL::Initialize()) {
1645e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    helper_->Destroy();
1655e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    return false;
1665e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
1675e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1685e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  helper_->stub()->AddDestructionObserver(this);
1695e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return true;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IOSurfaceImageTransportSurface::Destroy() {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnrefIOSurface();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper_->Destroy();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoOpGLSurfaceCGL::Destroy();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IOSurfaceImageTransportSurface::DeferDraws() {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The command buffer hit a draw/clear command that could clobber the
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IOSurface in use by an earlier SwapBuffers. If a Swap is pending, abort
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // processing of the command by returning true and unschedule until the Swap
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ack arrives.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if(did_unschedule_)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // Still unscheduled, so just return true.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_swap_buffers_pending_) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_unschedule_ = true;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper_->SetScheduled(false);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IOSurfaceImageTransportSurface::IsOffscreen() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IOSurfaceImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = context;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (made_current_)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OnResize(gfx::Size(1, 1), 1.f);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  made_current_ = true;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int IOSurfaceImageTransportSurface::GetBackingFrameBufferObject() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fbo_id_;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IOSurfaceImageTransportSurface::SetBackbufferAllocation(bool allocation) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (backbuffer_suggested_allocation_ == allocation)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backbuffer_suggested_allocation_ = allocation;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdjustBufferAllocation();
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IOSurfaceImageTransportSurface::SetFrontbufferAllocation(bool allocation) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frontbuffer_suggested_allocation_ == allocation)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frontbuffer_suggested_allocation_ = allocation;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdjustBufferAllocation();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IOSurfaceImageTransportSurface::AdjustBufferAllocation() {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On mac, the frontbuffer and backbuffer are the same buffer. The buffer is
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // free'd when both the browser and gpu processes have Unref'd the IOSurface.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!backbuffer_suggested_allocation_ &&
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !frontbuffer_suggested_allocation_ &&
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_surface_.get()) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnrefIOSurface();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper_->Suspend();
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (backbuffer_suggested_allocation_ && !io_surface_) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateIOSurface();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IOSurfaceImageTransportSurface::SwapBuffers() {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backbuffer_suggested_allocation_);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!frontbuffer_suggested_allocation_)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glFlush();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.surface_handle = io_surface_handle_;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.size = GetSize();
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  params.scale_factor = scale_factor_;
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.latency_info = latency_info_;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper_->SendAcceleratedSurfaceBuffersSwapped(params);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_swap_buffers_pending_);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_swap_buffers_pending_ = true;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IOSurfaceImageTransportSurface::PostSubBuffer(
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x, int y, int width, int height) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backbuffer_suggested_allocation_);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!frontbuffer_suggested_allocation_)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glFlush();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.surface_handle = io_surface_handle_;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.x = x;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.y = y;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.width = width;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.height = height;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.surface_size = GetSize();
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  params.surface_scale_factor = scale_factor_;
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.latency_info = latency_info_;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper_->SendAcceleratedSurfacePostSubBuffer(params);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_swap_buffers_pending_);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_swap_buffers_pending_ = true;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IOSurfaceImageTransportSurface::GetExtensions() {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extensions = gfx::GLSurface::GetExtensions();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions += extensions.empty() ? "" : " ";
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions += "GL_CHROMIUM_front_buffer_cached ";
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions += "GL_CHROMIUM_post_sub_buffer";
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extensions;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size IOSurfaceImageTransportSurface::GetSize() {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IOSurfaceImageTransportSurface::OnBufferPresented(
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_swap_buffers_pending_);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context_->share_group()->SetRendererID(params.renderer_id);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_swap_buffers_pending_ = false;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (did_unschedule_) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_unschedule_ = false;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper_->SetScheduled(true);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IOSurfaceImageTransportSurface::OnResizeViewACK() {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IOSurfaceImageTransportSurface::OnResize(gfx::Size size,
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                              float scale_factor) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This trace event is used in gpu_feature_browsertest.cc - the test will need
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be updated if this event is changed or moved.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT2("gpu", "IOSurfaceImageTransportSurface::OnResize",
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "old_width", size_.width(), "new_width", size.width());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Caching |context_| from OnMakeCurrent. It should still be current.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context_->IsCurrent(this));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = size;
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scale_factor_ = scale_factor;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateIOSurface();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IOSurfaceImageTransportSurface::SetLatencyInfo(
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ui::LatencyInfo& latency_info) {
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  latency_info_ = latency_info;
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void IOSurfaceImageTransportSurface::WakeUpGpu() {
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTIMPLEMENTED();
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3355e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void IOSurfaceImageTransportSurface::OnWillDestroyStub() {
3365e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  helper_->stub()->RemoveDestructionObserver(this);
3375e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  Destroy();
3385e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
3395e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IOSurfaceImageTransportSurface::UnrefIOSurface() {
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we have resources to destroy, then make sure that we have a current
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // context which we can use to delete the resources.
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (context_ || fbo_id_ || texture_id_ || depth_stencil_renderbuffer_id_) {
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(gfx::GLContext::GetCurrent() == context_);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(context_->IsCurrent(this));
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(CGLGetCurrentContext());
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fbo_id_) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glDeleteFramebuffersEXT(1, &fbo_id_);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fbo_id_ = 0;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (texture_id_) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glDeleteTextures(1, &texture_id_);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    texture_id_ = 0;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (depth_stencil_renderbuffer_id_) {
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    glDeleteRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    depth_stencil_renderbuffer_id_ = 0;
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_surface_.reset();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_surface_handle_ = 0;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IOSurfaceImageTransportSurface::CreateIOSurface() {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size new_rounded_size(RoundUpSurfaceDimension(size_.width()),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RoundUpSurfaceDimension(size_.height()));
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only recreate surface when the rounded up size has changed.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (io_surface_.get() && new_rounded_size == rounded_size_)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This trace event is used in gpu_feature_browsertest.cc - the test will need
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be updated if this event is changed or moved.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT2("gpu", "IOSurfaceImageTransportSurface::CreateIOSurface",
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "width", new_rounded_size.width(),
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "height", new_rounded_size.height());
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rounded_size_ = new_rounded_size;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint previous_texture_id = 0;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Free the old IO Surface first to reduce memory fragmentation.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnrefIOSurface();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGenFramebuffersEXT(1, &fbo_id_);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGenTextures(1, &texture_id_);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mac OS X and is required for IOSurface interoperability.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLenum target = GL_TEXTURE_RECTANGLE_ARB;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindTexture(target, texture_id_);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            GL_COLOR_ATTACHMENT0_EXT,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            target,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            texture_id_,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            0);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Search through the provided attributes; if the caller has
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // requested a stencil buffer, try to get one.
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int32 stencil_bits =
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      helper_->stub()->GetRequestedAttribute(EGL_STENCIL_SIZE);
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (stencil_bits > 0) {
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Create and bind the stencil buffer
420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool has_packed_depth_stencil =
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         GLSurface::ExtensionsContain(
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            "GL_EXT_packed_depth_stencil");
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (has_packed_depth_stencil) {
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            depth_stencil_renderbuffer_id_);
429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              rounded_size_.width(), rounded_size_.height());
431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  GL_STENCIL_ATTACHMENT_EXT,
433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  GL_RENDERBUFFER_EXT,
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  depth_stencil_renderbuffer_id_);
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If we asked for stencil but the extension isn't present,
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // it's OK to silently fail; subsequent code will/must check
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // for the presence of a stencil buffer before attempting to
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // do stencil-based operations.
441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a new IOSurface, which is the GPU resource that can be
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shared across processes.
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             0,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             &kCFTypeDictionaryKeyCallBacks,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             &kCFTypeDictionaryValueCallBacks));
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddIntegerValue(properties,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  io_surface_support->GetKIOSurfaceWidth(),
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  rounded_size_.width());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddIntegerValue(properties,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  io_surface_support->GetKIOSurfaceHeight(),
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  rounded_size_.height());
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddIntegerValue(properties,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  io_surface_support->GetKIOSurfaceBytesPerElement(), 4);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddBooleanValue(properties,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  io_surface_support->GetKIOSurfaceIsGlobal(), true);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // I believe we should be able to unreference the IOSurfaces without
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // synchronizing with the browser process because they are
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ultimately reference counted by the operating system.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_surface_.reset(io_surface_support->IOSurfaceCreate(properties));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_surface_handle_ = io_surface_support->IOSurfaceGetID(io_surface_);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't think we need to identify a plane.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint plane = 0;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CGLError cglerror =
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_surface_support->CGLTexImageIOSurface2D(
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<CGLContextObj>(context_->GetHandle()),
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          target,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GL_RGBA,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rounded_size_.width(),
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rounded_size_.height(),
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GL_BGRA,
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GL_UNSIGNED_INT_8_8_8_8_REV,
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          io_surface_.get(),
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          plane);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cglerror != kCGLNoError) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnrefIOSurface();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glFlush();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DLOG(ERROR) << "Framebuffer was incomplete: " << status;
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    UnrefIOSurface();
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glBindTexture(target, previous_texture_id);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The FBO remains bound for this GL context.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A subclass of GLSurfaceOSMesa that doesn't print an error message when
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// SwapBuffers() is called.
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DRTSurfaceOSMesa : public gfx::GLSurfaceOSMesa {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size doesn't matter, the surface is resized to the right size later.
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DRTSurfaceOSMesa() : GLSurfaceOSMesa(GL_RGBA, gfx::Size(1, 1)) {}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Implement a subset of GLSurface.
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SwapBuffers() OVERRIDE;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DRTSurfaceOSMesa() {}
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DRTSurfaceOSMesa);
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DRTSurfaceOSMesa::SwapBuffers() {
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool g_allow_os_mesa = false;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelManager* manager,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuCommandBufferStub* stub,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::GLSurfaceHandle& surface_handle) {
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(surface_handle.transport_type == gfx::NATIVE_TRANSPORT);
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (gfx::GetGLImplementation()) {
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case gfx::kGLImplementationDesktopGL:
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case gfx::kGLImplementationAppleGL:
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!io_surface_support) {
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        DLOG(WARNING) << "No IOSurface support";
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return scoped_refptr<gfx::GLSurface>();
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return scoped_refptr<gfx::GLSurface>(new IOSurfaceImageTransportSurface(
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          manager, stub, surface_handle.handle));
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Content shell in DRT mode spins up a gpu process which needs an
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // image transport surface, but that surface isn't used to read pixel
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // baselines. So this is mostly a dummy surface.
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!g_allow_os_mesa) {
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        NOTREACHED();
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return scoped_refptr<gfx::GLSurface>();
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scoped_refptr<gfx::GLSurface> surface(new DRTSurfaceOSMesa());
5477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!surface.get() || !surface->Initialize())
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return surface;
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          manager, stub, surface.get(), false));
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ImageTransportSurface::SetAllowOSMesaForTesting(bool allow) {
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_allow_os_mesa = allow;
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
560