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/client/gpu_memory_buffer_impl_surface_texture.h"
6
7#include "base/debug/trace_event.h"
8#include "base/logging.h"
9#include "content/common/android/surface_texture_lookup.h"
10#include "ui/gl/gl_bindings.h"
11
12namespace content {
13
14GpuMemoryBufferImplSurfaceTexture::GpuMemoryBufferImplSurfaceTexture(
15    const gfx::Size& size,
16    unsigned internalformat)
17    : GpuMemoryBufferImpl(size, internalformat),
18      native_window_(NULL),
19      stride_(0u) {}
20
21GpuMemoryBufferImplSurfaceTexture::~GpuMemoryBufferImplSurfaceTexture() {
22  if (native_window_)
23    ANativeWindow_release(native_window_);
24}
25
26// static
27bool GpuMemoryBufferImplSurfaceTexture::IsFormatSupported(
28    unsigned internalformat) {
29  switch (internalformat) {
30    case GL_RGBA8_OES:
31      return true;
32    default:
33      return false;
34  }
35}
36
37// static
38bool GpuMemoryBufferImplSurfaceTexture::IsUsageSupported(unsigned usage) {
39  switch (usage) {
40    case GL_IMAGE_MAP_CHROMIUM:
41      return true;
42    default:
43      return false;
44  }
45}
46
47// static
48bool GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(
49    unsigned internalformat,
50    unsigned usage) {
51  return IsFormatSupported(internalformat) && IsUsageSupported(usage);
52}
53
54// static
55int GpuMemoryBufferImplSurfaceTexture::WindowFormat(unsigned internalformat) {
56  switch (internalformat) {
57    case GL_RGBA8_OES:
58      return WINDOW_FORMAT_RGBA_8888;
59    default:
60      NOTREACHED();
61      return 0;
62  }
63}
64
65bool GpuMemoryBufferImplSurfaceTexture::InitializeFromHandle(
66    gfx::GpuMemoryBufferHandle handle) {
67  TRACE_EVENT0("gpu",
68               "GpuMemoryBufferImplSurfaceTexture::InitializeFromHandle");
69
70  DCHECK(IsFormatSupported(internalformat_));
71  DCHECK(!native_window_);
72  native_window_ = SurfaceTextureLookup::GetInstance()->AcquireNativeWidget(
73      handle.surface_texture_id.primary_id,
74      handle.surface_texture_id.secondary_id);
75  if (!native_window_)
76    return false;
77
78  ANativeWindow_setBuffersGeometry(native_window_,
79                                   size_.width(),
80                                   size_.height(),
81                                   WindowFormat(internalformat_));
82
83  surface_texture_id_ = handle.surface_texture_id;
84  return true;
85}
86
87void* GpuMemoryBufferImplSurfaceTexture::Map() {
88  TRACE_EVENT0("gpu", "GpuMemoryBufferImplSurfaceTexture::Map");
89
90  DCHECK(!mapped_);
91  DCHECK(native_window_);
92  ANativeWindow_Buffer buffer;
93  int status = ANativeWindow_lock(native_window_, &buffer, NULL);
94  if (status) {
95    VLOG(1) << "ANativeWindow_lock failed with error code: " << status;
96    return NULL;
97  }
98
99  DCHECK_LE(size_.width(), buffer.stride);
100  stride_ = buffer.stride * BytesPerPixel(internalformat_);
101  mapped_ = true;
102  return buffer.bits;
103}
104
105void GpuMemoryBufferImplSurfaceTexture::Unmap() {
106  TRACE_EVENT0("gpu", "GpuMemoryBufferImplSurfaceTexture::Unmap");
107
108  DCHECK(mapped_);
109  ANativeWindow_unlockAndPost(native_window_);
110  mapped_ = false;
111}
112
113uint32 GpuMemoryBufferImplSurfaceTexture::GetStride() const { return stride_; }
114
115gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSurfaceTexture::GetHandle()
116    const {
117  gfx::GpuMemoryBufferHandle handle;
118  handle.type = gfx::SURFACE_TEXTURE_BUFFER;
119  handle.surface_texture_id = surface_texture_id_;
120  return handle;
121}
122
123}  // namespace content
124