Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / image_transport_surface_iosurface_mac.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/image_transport_surface_iosurface_mac.h"
6
7 #include "content/common/gpu/gpu_messages.h"
8 #include "content/common/gpu/surface_handle_types_mac.h"
9
10 namespace content {
11 namespace {
12
13 // IOSurface dimensions will be rounded up to a multiple of this value in order
14 // to reduce memory thrashing during resize. This must be a power of 2.
15 const uint32 kIOSurfaceDimensionRoundup = 64;
16
17 int RoundUpSurfaceDimension(int number) {
18   DCHECK(number >= 0);
19   // Cast into unsigned space for portable bitwise ops.
20   uint32 unsigned_number = static_cast<uint32>(number);
21   uint32 roundup_sub_1 = kIOSurfaceDimensionRoundup - 1;
22   unsigned_number = (unsigned_number + roundup_sub_1) & ~roundup_sub_1;
23   return static_cast<int>(unsigned_number);
24 }
25
26 void AddBooleanValue(CFMutableDictionaryRef dictionary,
27                      const CFStringRef key,
28                      bool value) {
29   CFDictionaryAddValue(dictionary, key,
30                        (value ? kCFBooleanTrue : kCFBooleanFalse));
31 }
32
33 void AddIntegerValue(CFMutableDictionaryRef dictionary,
34                      const CFStringRef key,
35                      int32 value) {
36   base::ScopedCFTypeRef<CFNumberRef> number(
37       CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
38   CFDictionaryAddValue(dictionary, key, number.get());
39 }
40
41 }  // namespace
42
43 IOSurfaceStorageProvider::IOSurfaceStorageProvider(
44     ImageTransportSurfaceFBO* transport_surface)
45         : transport_surface_(transport_surface) {}
46
47 IOSurfaceStorageProvider::~IOSurfaceStorageProvider() {
48   DCHECK(!io_surface_);
49 }
50
51 gfx::Size IOSurfaceStorageProvider::GetRoundedSize(gfx::Size size) {
52   return gfx::Size(RoundUpSurfaceDimension(size.width()),
53                    RoundUpSurfaceDimension(size.height()));
54 }
55
56 bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
57     CGLContextObj context, GLuint texture,
58     gfx::Size pixel_size, float scale_factor) {
59   // Allocate a new IOSurface, which is the GPU resource that can be
60   // shared across processes.
61   base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
62   properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
63                                              0,
64                                              &kCFTypeDictionaryKeyCallBacks,
65                                              &kCFTypeDictionaryValueCallBacks));
66   AddIntegerValue(properties,
67                   kIOSurfaceWidth,
68                   pixel_size.width());
69   AddIntegerValue(properties,
70                   kIOSurfaceHeight,
71                   pixel_size.height());
72   AddIntegerValue(properties,
73                   kIOSurfaceBytesPerElement, 4);
74   AddBooleanValue(properties,
75                   kIOSurfaceIsGlobal, true);
76   // I believe we should be able to unreference the IOSurfaces without
77   // synchronizing with the browser process because they are
78   // ultimately reference counted by the operating system.
79   io_surface_.reset(IOSurfaceCreate(properties));
80   io_surface_id_ = IOSurfaceGetID(io_surface_);
81
82   // Don't think we need to identify a plane.
83   GLuint plane = 0;
84   CGLError cglerror = CGLTexImageIOSurface2D(
85       context,
86       GL_TEXTURE_RECTANGLE_ARB,
87       GL_RGBA,
88       pixel_size.width(),
89       pixel_size.height(),
90       GL_BGRA,
91       GL_UNSIGNED_INT_8_8_8_8_REV,
92       io_surface_.get(),
93       plane);
94   if (cglerror != kCGLNoError) {
95     DLOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cglerror;
96     return false;
97   }
98
99   glFlush();
100   return true;
101 }
102
103 void IOSurfaceStorageProvider::FreeColorBufferStorage() {
104   io_surface_.reset();
105   io_surface_id_ = 0;
106 }
107
108 void IOSurfaceStorageProvider::SwapBuffers(
109     const gfx::Size& size, float scale_factor) {
110   // The browser compositor will throttle itself, so we are free to unblock the
111   // context immediately. Make sure that the browser is doing its throttling
112   // appropriately by ensuring that the previous swap was acknowledged before
113   // we get another swap.
114   DCHECK(pending_swapped_surfaces_.empty());
115   pending_swapped_surfaces_.push_back(io_surface_);
116
117   transport_surface_->SendSwapBuffers(
118       SurfaceHandleFromIOSurfaceID(io_surface_id_), size, scale_factor);
119 }
120
121 void IOSurfaceStorageProvider::WillWriteToBackbuffer() {
122 }
123
124 void IOSurfaceStorageProvider::DiscardBackbuffer() {
125 }
126
127 void IOSurfaceStorageProvider::SwapBuffersAckedByBrowser() {
128   DCHECK(!pending_swapped_surfaces_.empty());
129   pending_swapped_surfaces_.pop_front();
130 }
131
132 }  //  namespace content