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 "ui/ozone/platform/dri/gbm_surface.h" 6 7 #include <gbm.h> 8 9 #include "base/logging.h" 10 #include "third_party/skia/include/core/SkImageInfo.h" 11 #include "ui/ozone/platform/dri/buffer_data.h" 12 #include "ui/ozone/platform/dri/dri_buffer.h" 13 #include "ui/ozone/platform/dri/dri_wrapper.h" 14 #include "ui/ozone/platform/dri/hardware_display_controller.h" 15 16 namespace ui { 17 18 GbmSurface::GbmSurface(gbm_device* device, 19 DriWrapper* dri, 20 const gfx::Size& size) 21 : gbm_device_(device), 22 dri_(dri), 23 size_(size), 24 native_surface_(NULL), 25 buffers_(), 26 front_buffer_(0) { 27 for (size_t i = 0; i < arraysize(buffers_); ++i) 28 buffers_[i] = NULL; 29 } 30 31 GbmSurface::~GbmSurface() { 32 for (size_t i = 0; i < arraysize(buffers_); ++i) { 33 if (buffers_[i]) { 34 gbm_surface_release_buffer(native_surface_, buffers_[i]); 35 } 36 } 37 38 if (native_surface_) 39 gbm_surface_destroy(native_surface_); 40 } 41 42 bool GbmSurface::Initialize() { 43 // TODO(dnicoara) Check underlying system support for pixel format. 44 native_surface_ = gbm_surface_create( 45 gbm_device_, 46 size_.width(), 47 size_.height(), 48 GBM_BO_FORMAT_XRGB8888, 49 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); 50 51 if (!native_surface_) 52 return false; 53 54 dumb_buffer_.reset(new DriBuffer(dri_)); 55 if (!dumb_buffer_->Initialize(SkImageInfo::MakeN32Premul(size_.width(), 56 size_.height()))) 57 return false; 58 59 return true; 60 } 61 62 uint32_t GbmSurface::GetFramebufferId() const { 63 if (!buffers_[front_buffer_ ^ 1]) 64 return dumb_buffer_->framebuffer(); 65 66 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); 67 CHECK(data); 68 return data->framebuffer(); 69 } 70 71 uint32_t GbmSurface::GetHandle() const { 72 if (!buffers_[front_buffer_ ^ 1]) 73 return dumb_buffer_->handle(); 74 75 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); 76 CHECK(data); 77 return data->handle(); 78 } 79 80 gfx::Size GbmSurface::Size() const { 81 return size_; 82 } 83 84 void GbmSurface::SwapBuffers() { 85 // If there was a frontbuffer, is no longer active. Release it back to GBM. 86 if (buffers_[front_buffer_]) 87 gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]); 88 89 // Update the index to the frontbuffer. 90 front_buffer_ ^= 1; 91 // We've just released it. Since GBM doesn't guarantee we'll get the same 92 // buffer back, we set it to NULL so we don't keep track of objects that may 93 // have been destroyed. 94 buffers_[front_buffer_ ^ 1] = NULL; 95 } 96 97 void GbmSurface::LockCurrentDrawable() { 98 CHECK(native_surface_); 99 // Lock the buffer we want to display. 100 buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_); 101 102 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); 103 // If it is a new buffer, it won't have any data associated with it. So we 104 // create it. On creation it will associate itself with the buffer and 105 // register the buffer. 106 if (!data) { 107 data = BufferData::CreateData(dri_, buffers_[front_buffer_ ^ 1]); 108 DCHECK(data) << "Failed to associate the buffer with the controller"; 109 } 110 } 111 112 } // namespace ui 113