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