1// Copyright 2013 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/gfx/ozone/dri/dri_surface.h" 6 7#include <errno.h> 8#include <sys/mman.h> 9#include <sys/types.h> 10#include <xf86drm.h> 11 12#include "base/logging.h" 13#include "third_party/skia/include/core/SkBitmap.h" 14#include "third_party/skia/include/core/SkBitmapDevice.h" 15#include "third_party/skia/include/core/SkCanvas.h" 16#include "ui/gfx/ozone/dri/dri_skbitmap.h" 17#include "ui/gfx/ozone/dri/hardware_display_controller.h" 18#include "ui/gfx/skia_util.h" 19 20namespace gfx { 21 22namespace { 23 24// Extends the SkBitmapDevice to allow setting the SkPixelRef. We use the setter 25// to change the SkPixelRef such that the device always points to the 26// backbuffer. 27class CustomSkBitmapDevice : public SkBitmapDevice { 28 public: 29 CustomSkBitmapDevice(const SkBitmap& bitmap) : SkBitmapDevice(bitmap) {} 30 virtual ~CustomSkBitmapDevice() {} 31 32 void SetPixelRef(SkPixelRef* pixel_ref) { setPixelRef(pixel_ref, 0); } 33 34 private: 35 DISALLOW_COPY_AND_ASSIGN(CustomSkBitmapDevice); 36}; 37 38} // namespace 39 40//////////////////////////////////////////////////////////////////////////////// 41// DriSurface implementation 42 43DriSurface::DriSurface( 44 HardwareDisplayController* controller) 45 : controller_(controller), 46 bitmaps_(), 47 front_buffer_(0) { 48} 49 50DriSurface::~DriSurface() { 51} 52 53bool DriSurface::Initialize() { 54 for (int i = 0; i < 2; ++i) { 55 bitmaps_[i].reset(CreateBuffer()); 56 // TODO(dnicoara) Should select the configuration based on what the 57 // underlying system supports. 58 bitmaps_[i]->setConfig(SkBitmap::kARGB_8888_Config, 59 controller_->get_mode().hdisplay, 60 controller_->get_mode().vdisplay); 61 62 if (!bitmaps_[i]->Initialize()) { 63 return false; 64 } 65 } 66 67 skia_device_ = skia::AdoptRef( 68 new CustomSkBitmapDevice(*bitmaps_[front_buffer_ ^ 1].get())); 69 skia_canvas_ = skia::AdoptRef(new SkCanvas(skia_device_.get())); 70 71 return true; 72} 73 74uint32_t DriSurface::GetFramebufferId() const { 75 CHECK(bitmaps_[0].get() && bitmaps_[1].get()); 76 return bitmaps_[front_buffer_ ^ 1]->get_framebuffer(); 77} 78 79// This call is made after the hardware just started displaying our back buffer. 80// We need to update our pointer reference and synchronize the two buffers. 81void DriSurface::SwapBuffers() { 82 CHECK(bitmaps_[0].get() && bitmaps_[1].get()); 83 84 // Update our front buffer pointer. 85 front_buffer_ ^= 1; 86 87 // Unlocking will unset the pixel pointer, so it won't be pointing to the old 88 // PixelRef. 89 skia_device_->accessBitmap(false).unlockPixels(); 90 // Update the backing pixels for the bitmap device. 91 static_cast<CustomSkBitmapDevice*>(skia_device_.get())->SetPixelRef( 92 bitmaps_[front_buffer_ ^ 1]->pixelRef()); 93 // Locking the pixels will set the pixel pointer based on the PixelRef value. 94 skia_device_->accessBitmap(false).lockPixels(); 95 96 SkIRect device_damage; 97 skia_canvas_->getClipDeviceBounds(&device_damage); 98 SkRect damage = SkRect::Make(device_damage); 99 100 skia_canvas_->drawBitmapRectToRect(*bitmaps_[front_buffer_].get(), 101 &damage, 102 damage); 103} 104 105SkCanvas* DriSurface::GetDrawableForWidget() { 106 return skia_canvas_.get(); 107} 108 109DriSkBitmap* DriSurface::CreateBuffer() { 110 return new DriSkBitmap(controller_->get_fd()); 111} 112 113} // namespace gfx 114