Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/ozone/platform/dri/gbm_surface.h" | 5 #include "ui/ozone/platform/dri/gbm_surface.h" |
| 6 | 6 |
| 7 #include <gbm.h> | 7 #include <gbm.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "third_party/skia/include/core/SkImageInfo.h" | 10 #include "third_party/skia/include/core/SkImageInfo.h" |
| 11 #include "ui/ozone/platform/dri/buffer_data.h" | 11 #include "ui/ozone/platform/dri/buffer_data.h" |
| 12 #include "ui/ozone/platform/dri/dri_buffer.h" | 12 #include "ui/ozone/platform/dri/dri_buffer.h" |
| 13 #include "ui/ozone/platform/dri/dri_wrapper.h" | 13 #include "ui/ozone/platform/dri/dri_wrapper.h" |
| 14 #include "ui/ozone/platform/dri/hardware_display_controller.h" | 14 #include "ui/ozone/platform/dri/hardware_display_controller.h" |
| 15 #include "ui/ozone/platform/dri/scanout_buffer.h" | |
| 15 | 16 |
| 16 namespace ui { | 17 namespace ui { |
| 17 | 18 |
| 19 namespace { | |
| 20 | |
| 21 // Pixel configuration for the current buffer format. | |
| 22 // TODO(dnicoara) These will need to change once we query the hardware for | |
| 23 // supported configurations. | |
| 24 const uint8_t kColorDepth = 24; | |
| 25 const uint8_t kPixelDepth = 32; | |
| 26 | |
| 27 } // namespace | |
| 28 | |
| 29 class GbmSurface::GbmSurfaceBuffer : public ScanoutBuffer { | |
|
dnicoara
2014/07/18 19:30:20
This is pretty much BufferData with a few addition
alexst (slow to review)
2014/07/18 19:49:07
This looks a lot like https://code.google.com/p/ch
dnicoara
2014/07/18 20:04:19
I initially wanted to do that, but the semantics o
alexst (slow to review)
2014/07/18 21:11:31
I've been looking at the details and I see what yo
dnicoara
2014/07/18 21:48:27
Done.
| |
| 30 public: | |
| 31 static scoped_refptr<GbmSurfaceBuffer> CreateBuffer(DriWrapper* dri, | |
| 32 gbm_bo* buffer); | |
| 33 static scoped_refptr<GbmSurfaceBuffer> GetBuffer(gbm_bo* buffer); | |
| 34 | |
| 35 gbm_bo* bo() const { return bo_; } | |
| 36 | |
| 37 // ScanoutBuffer: | |
| 38 virtual uint32_t GetFramebufferId() const OVERRIDE; | |
| 39 virtual uint32_t GetHandle() const OVERRIDE; | |
| 40 virtual gfx::Size GetSize() const OVERRIDE; | |
| 41 | |
| 42 private: | |
| 43 GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo); | |
| 44 virtual ~GbmSurfaceBuffer(); | |
| 45 | |
| 46 static void Destroy(gbm_bo* buffer, void* data); | |
| 47 | |
| 48 // This buffer is special and is released by GBM at any point in time (as | |
| 49 // long as it isn't being used). Since GBM should be the only one to | |
| 50 // release this buffer, keep a self-reference in order to keep this alive. | |
| 51 // When GBM calls Destroy(..) the self-reference will dissapear and this will | |
| 52 // be destroyed. | |
| 53 scoped_refptr<GbmSurfaceBuffer> self_; | |
| 54 | |
| 55 DriWrapper* dri_; | |
| 56 gbm_bo* bo_; | |
| 57 uint32_t framebuffer_; | |
| 58 | |
| 59 DISALLOW_COPY_AND_ASSIGN(GbmSurfaceBuffer); | |
| 60 }; | |
| 61 | |
| 62 GbmSurface::GbmSurfaceBuffer::GbmSurfaceBuffer(DriWrapper* dri, gbm_bo* bo) | |
| 63 : dri_(dri), bo_(bo), framebuffer_(0) { | |
| 64 if (!dri_->AddFramebuffer(gbm_bo_get_width(bo), | |
| 65 gbm_bo_get_height(bo), | |
| 66 kColorDepth, | |
| 67 kPixelDepth, | |
| 68 gbm_bo_get_stride(bo), | |
| 69 gbm_bo_get_handle(bo).u32, | |
| 70 &framebuffer_)) { | |
| 71 LOG(ERROR) << "Failed to register buffer"; | |
| 72 return; | |
| 73 } | |
| 74 | |
| 75 self_ = this; | |
| 76 gbm_bo_set_user_data(bo, this, GbmSurfaceBuffer::Destroy); | |
| 77 } | |
| 78 | |
| 79 GbmSurface::GbmSurfaceBuffer::~GbmSurfaceBuffer() { | |
| 80 if (framebuffer_) | |
| 81 dri_->RemoveFramebuffer(framebuffer_); | |
| 82 } | |
| 83 | |
| 84 // static | |
| 85 scoped_refptr<GbmSurface::GbmSurfaceBuffer> | |
| 86 GbmSurface::GbmSurfaceBuffer::CreateBuffer(DriWrapper* dri, gbm_bo* buffer) { | |
| 87 scoped_refptr<GbmSurfaceBuffer> scoped_buffer(new GbmSurfaceBuffer(dri, | |
| 88 buffer)); | |
| 89 if (!scoped_buffer->GetFramebufferId()) | |
| 90 return NULL; | |
| 91 | |
| 92 return scoped_buffer; | |
| 93 } | |
| 94 | |
| 95 // static | |
| 96 scoped_refptr<GbmSurface::GbmSurfaceBuffer> | |
| 97 GbmSurface::GbmSurfaceBuffer::GetBuffer(gbm_bo* buffer) { | |
| 98 return scoped_refptr<GbmSurfaceBuffer>( | |
| 99 static_cast<GbmSurfaceBuffer*>(gbm_bo_get_user_data(buffer))); | |
| 100 } | |
| 101 | |
| 102 // static | |
| 103 void GbmSurface::GbmSurfaceBuffer::Destroy(gbm_bo* buffer, void* data) { | |
| 104 GbmSurfaceBuffer* scoped_buffer = static_cast<GbmSurfaceBuffer*>(data); | |
| 105 scoped_buffer->self_ = NULL; | |
| 106 } | |
| 107 | |
| 108 uint32_t GbmSurface::GbmSurfaceBuffer::GetFramebufferId() const { | |
| 109 return framebuffer_; | |
| 110 } | |
| 111 | |
| 112 uint32_t GbmSurface::GbmSurfaceBuffer::GetHandle() const { | |
| 113 return gbm_bo_get_handle(bo_).u32; | |
| 114 } | |
| 115 | |
| 116 gfx::Size GbmSurface::GbmSurfaceBuffer::GetSize() const { | |
| 117 return gfx::Size(gbm_bo_get_width(bo_), gbm_bo_get_height(bo_)); | |
| 118 } | |
| 119 | |
| 18 GbmSurface::GbmSurface(gbm_device* device, | 120 GbmSurface::GbmSurface(gbm_device* device, |
| 19 DriWrapper* dri, | 121 DriWrapper* dri, |
| 20 const gfx::Size& size) | 122 const gfx::Size& size) |
| 21 : gbm_device_(device), | 123 : gbm_device_(device), |
| 22 dri_(dri), | 124 dri_(dri), |
| 23 size_(size), | 125 size_(size), |
| 24 native_surface_(NULL), | 126 native_surface_(NULL), |
| 25 buffers_(), | 127 buffers_(), |
| 26 front_buffer_(0) { | 128 front_buffer_(0) { |
| 27 for (size_t i = 0; i < arraysize(buffers_); ++i) | 129 for (size_t i = 0; i < arraysize(buffers_); ++i) |
| 28 buffers_[i] = NULL; | 130 buffers_[i] = NULL; |
| 29 } | 131 } |
| 30 | 132 |
| 31 GbmSurface::~GbmSurface() { | 133 GbmSurface::~GbmSurface() { |
| 32 for (size_t i = 0; i < arraysize(buffers_); ++i) { | 134 for (size_t i = 0; i < arraysize(buffers_); ++i) { |
| 33 if (buffers_[i]) { | 135 if (buffers_[i]) { |
| 34 gbm_surface_release_buffer(native_surface_, buffers_[i]); | 136 gbm_surface_release_buffer(native_surface_, buffers_[i]->bo()); |
| 35 } | 137 } |
| 36 } | 138 } |
| 37 | 139 |
| 38 if (native_surface_) | 140 if (native_surface_) |
| 39 gbm_surface_destroy(native_surface_); | 141 gbm_surface_destroy(native_surface_); |
| 40 } | 142 } |
| 41 | 143 |
| 42 bool GbmSurface::Initialize() { | 144 bool GbmSurface::Initialize() { |
| 43 // TODO(dnicoara) Check underlying system support for pixel format. | 145 // TODO(dnicoara) Check underlying system support for pixel format. |
| 44 native_surface_ = gbm_surface_create( | 146 native_surface_ = gbm_surface_create( |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 56 size_.height()))) | 158 size_.height()))) |
| 57 return false; | 159 return false; |
| 58 | 160 |
| 59 return true; | 161 return true; |
| 60 } | 162 } |
| 61 | 163 |
| 62 uint32_t GbmSurface::GetFramebufferId() const { | 164 uint32_t GbmSurface::GetFramebufferId() const { |
| 63 if (!buffers_[front_buffer_ ^ 1]) | 165 if (!buffers_[front_buffer_ ^ 1]) |
| 64 return dumb_buffer_->GetFramebufferId(); | 166 return dumb_buffer_->GetFramebufferId(); |
| 65 | 167 |
| 66 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); | 168 return buffers_[front_buffer_ ^ 1]->GetFramebufferId(); |
| 67 CHECK(data); | |
| 68 return data->framebuffer(); | |
| 69 } | 169 } |
| 70 | 170 |
| 71 uint32_t GbmSurface::GetHandle() const { | 171 uint32_t GbmSurface::GetHandle() const { |
| 72 if (!buffers_[front_buffer_ ^ 1]) | 172 if (!buffers_[front_buffer_ ^ 1]) |
| 73 return dumb_buffer_->GetHandle(); | 173 return dumb_buffer_->GetHandle(); |
| 74 | 174 |
| 75 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); | 175 return buffers_[front_buffer_ ^ 1]->GetHandle(); |
| 76 CHECK(data); | |
| 77 return data->handle(); | |
| 78 } | 176 } |
| 79 | 177 |
| 80 gfx::Size GbmSurface::Size() const { | 178 gfx::Size GbmSurface::Size() const { |
| 81 return size_; | 179 return size_; |
| 82 } | 180 } |
| 83 | 181 |
| 84 // Before scheduling the backbuffer to be scanned out we need to "lock" it. | 182 // Before scheduling the backbuffer to be scanned out we need to "lock" it. |
| 85 // When we lock it, GBM will give a pointer to a buffer representing the | 183 // When we lock it, GBM will give a pointer to a buffer representing the |
| 86 // backbuffer. It will also update its information on which buffers can not be | 184 // backbuffer. It will also update its information on which buffers can not be |
| 87 // used for drawing. The buffer will be released when the page flip event | 185 // used for drawing. The buffer will be released when the page flip event |
| 88 // occurs (see SwapBuffers). This is called from HardwareDisplayController | 186 // occurs (see SwapBuffers). This is called from HardwareDisplayController |
| 89 // before scheduling a page flip. | 187 // before scheduling a page flip. |
| 90 void GbmSurface::PreSwapBuffers() { | 188 void GbmSurface::PreSwapBuffers() { |
| 91 CHECK(native_surface_); | 189 CHECK(native_surface_); |
| 92 // Lock the buffer we want to display. | 190 // Lock the buffer we want to display. |
| 93 buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_); | 191 gbm_bo* bo = gbm_surface_lock_front_buffer(native_surface_); |
| 94 | 192 |
| 95 BufferData* data = BufferData::GetData(buffers_[front_buffer_ ^ 1]); | 193 buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::GetBuffer(bo); |
| 96 // If it is a new buffer, it won't have any data associated with it. So we | 194 // If it is a new buffer, it won't have any data associated with it. So we |
| 97 // create it. On creation it will associate itself with the buffer and | 195 // create it. On creation it will associate itself with the buffer and |
| 98 // register the buffer. | 196 // register the buffer. |
| 99 if (!data) { | 197 if (!buffers_[front_buffer_ ^ 1]) { |
| 100 data = BufferData::CreateData(dri_, buffers_[front_buffer_ ^ 1]); | 198 buffers_[front_buffer_ ^ 1] = GbmSurfaceBuffer::CreateBuffer(dri_, bo); |
| 101 DCHECK(data) << "Failed to associate the buffer with the controller"; | 199 DCHECK(buffers_[front_buffer_ ^ 1]) |
| 200 << "Failed to associate the buffer with the controller"; | |
| 102 } | 201 } |
| 103 } | 202 } |
| 104 | 203 |
| 105 void GbmSurface::SwapBuffers() { | 204 void GbmSurface::SwapBuffers() { |
| 106 // If there was a frontbuffer, is no longer active. Release it back to GBM. | 205 // If there was a frontbuffer, is no longer active. Release it back to GBM. |
| 107 if (buffers_[front_buffer_]) | 206 if (buffers_[front_buffer_]) |
| 108 gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]); | 207 gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]->bo()); |
| 109 | 208 |
| 110 // Update the index to the frontbuffer. | 209 // Update the index to the frontbuffer. |
| 111 front_buffer_ ^= 1; | 210 front_buffer_ ^= 1; |
| 112 // We've just released it. Since GBM doesn't guarantee we'll get the same | 211 // We've just released it. Since GBM doesn't guarantee we'll get the same |
| 113 // buffer back, we set it to NULL so we don't keep track of objects that may | 212 // buffer back, we set it to NULL so we don't keep track of objects that may |
| 114 // have been destroyed. | 213 // have been destroyed. |
| 115 buffers_[front_buffer_ ^ 1] = NULL; | 214 buffers_[front_buffer_ ^ 1] = NULL; |
| 116 } | 215 } |
| 117 | 216 |
| 118 } // namespace ui | 217 } // namespace ui |
| OLD | NEW |