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 10namespace content { 11namespace { 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. 15const uint32 kIOSurfaceDimensionRoundup = 64; 16 17int 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 26void AddBooleanValue(CFMutableDictionaryRef dictionary, 27 const CFStringRef key, 28 bool value) { 29 CFDictionaryAddValue(dictionary, key, 30 (value ? kCFBooleanTrue : kCFBooleanFalse)); 31} 32 33void 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 43IOSurfaceStorageProvider::IOSurfaceStorageProvider( 44 ImageTransportSurfaceFBO* transport_surface) 45 : transport_surface_(transport_surface) {} 46 47IOSurfaceStorageProvider::~IOSurfaceStorageProvider() { 48 DCHECK(!io_surface_); 49} 50 51gfx::Size IOSurfaceStorageProvider::GetRoundedSize(gfx::Size size) { 52 return gfx::Size(RoundUpSurfaceDimension(size.width()), 53 RoundUpSurfaceDimension(size.height())); 54} 55 56bool 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 103void IOSurfaceStorageProvider::FreeColorBufferStorage() { 104 io_surface_.reset(); 105 io_surface_id_ = 0; 106} 107 108void 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 121void IOSurfaceStorageProvider::WillWriteToBackbuffer() { 122} 123 124void IOSurfaceStorageProvider::DiscardBackbuffer() { 125} 126 127void IOSurfaceStorageProvider::SwapBuffersAckedByBrowser() { 128 DCHECK(!pending_swapped_surfaces_.empty()); 129 pending_swapped_surfaces_.pop_front(); 130} 131 132} // namespace content 133