15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "third_party/mesa/src/include/GL/osmesa.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_osmesa.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gl/scoped_make_current.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)GLSurfaceOSMesa::GLSurfaceOSMesa(OSMesaSurfaceFormat format,
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                 const gfx::Size& size)
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : size_(size) {
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  switch (format) {
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case OSMesaSurfaceFormatBGRA:
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      format_ = OSMESA_BGRA;
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case OSMesaSurfaceFormatRGBA:
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      format_ = OSMESA_RGBA;
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Implementations of OSMesa surface do not support having a 0 size. In such
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // cases use a (1, 1) surface.
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (size_.GetArea() == 0)
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_.SetSize(1, 1);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceOSMesa::Initialize() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Resize(size_);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLSurfaceOSMesa::Destroy() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.reset();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceOSMesa::Resize(const gfx::Size& new_size) {
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLContext* current_context = GLContext::GetCurrent();
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool was_current =
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      current_context && current_context->IsCurrent(this);
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (was_current) {
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_make_current.reset(
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new ui::ScopedMakeCurrent(current_context, this));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_context->ReleaseCurrent(this);
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Preserve the old buffer.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<int32[]> old_buffer(buffer_.release());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a new one.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.reset(new int32[new_size.GetArea()]);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(buffer_.get(), 0, new_size.GetArea() * sizeof(buffer_[0]));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy the old back buffer into the new buffer.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_buffer.get()) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int copy_width = std::min(size_.width(), new_size.width());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int copy_height = std::min(size_.height(), new_size.height());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int y = 0; y < copy_height; ++y) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int x = 0; x < copy_width; ++x) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buffer_[y * new_size.width() + x] = old_buffer[y * size_.width() + x];
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = new_size;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceOSMesa::IsOffscreen() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLSurfaceOSMesa::SwapBuffers() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Should not call SwapBuffers on an GLSurfaceOSMesa.";
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size GLSurfaceOSMesa::GetSize() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLSurfaceOSMesa::GetHandle() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buffer_.get();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned GLSurfaceOSMesa::GetFormat() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return format_;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLSurfaceOSMesa::~GLSurfaceOSMesa() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool GLSurfaceOSMesaHeadless::IsOffscreen() { return false; }
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool GLSurfaceOSMesaHeadless::SwapBuffers() { return true; }
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
102effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochGLSurfaceOSMesaHeadless::GLSurfaceOSMesaHeadless()
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, gfx::Size(1, 1)) {
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
106effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochGLSurfaceOSMesaHeadless::~GLSurfaceOSMesaHeadless() { Destroy(); }
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
109