1 // Copyright (c) 2012 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.
5 #include "content/renderer/gpu/compositor_software_output_device_gl_adapter.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "third_party/skia/include/core/SkBitmap.h"
10 #include "third_party/skia/include/core/SkPixelRef.h"
11 #include "third_party/skia/include/core/SkDevice.h"
12 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
15 #include <GLES2/gl2.h>
17 using WebKit::WebImage
;
18 using WebKit::WebGraphicsContext3D
;
19 using WebKit::WebSize
;
23 //------------------------------------------------------------------------------
25 CompositorSoftwareOutputDeviceGLAdapter::
26 CompositorSoftwareOutputDeviceGLAdapter(WebGraphicsContext3D
* context3D
)
27 : initialized_(false),
32 framebuffer_texture_id_(0),
33 context3d_(context3D
),
34 locked_for_write_(false) {
37 CompositorSoftwareOutputDeviceGLAdapter::
38 ~CompositorSoftwareOutputDeviceGLAdapter() {
42 WebImage
* CompositorSoftwareOutputDeviceGLAdapter::Lock(bool forWrite
) {
43 locked_for_write_
= forWrite
;
44 image_
= device_
->accessBitmap(forWrite
);
48 void CompositorSoftwareOutputDeviceGLAdapter::Unlock() {
49 if (locked_for_write_
)
50 Draw(device_
->accessBitmap(false).pixelRef()->pixels());
54 void CompositorSoftwareOutputDeviceGLAdapter::DidChangeViewportSize(
59 if (framebuffer_texture_size_
!= gfx::Size(size
))
63 void CompositorSoftwareOutputDeviceGLAdapter::Initialize() {
64 // Vertex shader that flips the y axis.
65 static const char g_vertex_shader
[] =
66 "attribute vec4 a_Position;"
67 "attribute vec2 a_texCoord;"
68 "varying vec2 v_texCoord;"
70 " gl_Position = a_Position;"
71 " gl_Position.y = -gl_Position.y;"
72 " v_texCoord = a_texCoord;"
75 // Pixel shader that swizzles RGBA -> BGRA.
76 static const char g_fragment_shader
[] =
77 "precision mediump float;"
78 "varying vec2 v_texCoord;"
79 "uniform sampler2D s_texture;"
81 " gl_FragColor = texture2D(s_texture, v_texCoord).bgra;"
84 const GLfloat attribs
[] = {
95 context3d_
->makeContextCurrent();
97 vertex_shader_
= context3d_
->createShader(GL_VERTEX_SHADER
);
98 context3d_
->shaderSource(vertex_shader_
, g_vertex_shader
);
99 context3d_
->compileShader(vertex_shader_
);
101 fragment_shader_
= context3d_
->createShader(GL_FRAGMENT_SHADER
);
102 context3d_
->shaderSource(fragment_shader_
, g_fragment_shader
);
103 context3d_
->compileShader(fragment_shader_
);
105 program_
= context3d_
->createProgram();
106 context3d_
->attachShader(program_
, vertex_shader_
);
107 context3d_
->attachShader(program_
, fragment_shader_
);
109 vertex_buffer_
= context3d_
->createBuffer();
110 context3d_
->bindBuffer(GL_ARRAY_BUFFER
, vertex_buffer_
);
111 context3d_
->bufferData(GL_ARRAY_BUFFER
, 16 * sizeof(float), attribs
,
113 context3d_
->enableVertexAttribArray(0);
114 context3d_
->vertexAttribPointer(0, 2, GL_FLOAT
, GL_FALSE
, 0, 0);
115 context3d_
->bindAttribLocation(program_
, 0, "a_Position");
116 context3d_
->enableVertexAttribArray(1);
117 context3d_
->vertexAttribPointer(
118 1, 2, GL_FLOAT
, GL_FALSE
, 0, 8 * sizeof(GLfloat
));
119 context3d_
->bindAttribLocation(program_
, 1, "a_texCoord");
121 context3d_
->linkProgram(program_
);
122 context3d_
->useProgram(program_
);
124 int texture_uniform
= context3d_
->getUniformLocation(program_
, "s_texture");
125 context3d_
->uniform1i(texture_uniform
, 0);
126 context3d_
->disable(GL_SCISSOR_TEST
);
127 context3d_
->clearColor(0, 0, 1, 1);
132 void CompositorSoftwareOutputDeviceGLAdapter::Destroy() {
136 context3d_
->makeContextCurrent();
137 context3d_
->deleteShader(vertex_shader_
);
138 context3d_
->deleteShader(fragment_shader_
);
139 context3d_
->deleteProgram(program_
);
140 context3d_
->deleteBuffer(vertex_buffer_
);
141 if (framebuffer_texture_id_
)
142 context3d_
->deleteTexture(framebuffer_texture_id_
);
145 void CompositorSoftwareOutputDeviceGLAdapter::Resize(
146 const gfx::Size
& viewport_size
) {
147 framebuffer_texture_size_
= viewport_size
;
148 device_
.reset(new SkDevice(SkBitmap::kARGB_8888_Config
,
149 viewport_size
.width(), viewport_size
.height(), true));
151 context3d_
->makeContextCurrent();
152 context3d_
->ensureBackbufferCHROMIUM();
153 framebuffer_texture_id_
= context3d_
->createTexture();
154 context3d_
->bindTexture(GL_TEXTURE_2D
, framebuffer_texture_id_
);
155 context3d_
->texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
156 context3d_
->texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
157 context3d_
->texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
158 context3d_
->texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
160 context3d_
->viewport(0, 0, viewport_size
.width(), viewport_size
.height());
161 context3d_
->reshape(viewport_size
.width(), viewport_size
.height());
164 void CompositorSoftwareOutputDeviceGLAdapter::Draw(void* pixels
) {
165 TRACE_EVENT0("renderer", "CompositorSoftwareOutputDeviceGLAdapter::Draw");
168 if (!framebuffer_texture_id_
)
171 context3d_
->makeContextCurrent();
172 context3d_
->ensureBackbufferCHROMIUM();
173 context3d_
->clear(GL_COLOR_BUFFER_BIT
);
175 context3d_
->texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
,
176 framebuffer_texture_size_
.width(), framebuffer_texture_size_
.height(),
177 0, GL_RGBA
, GL_UNSIGNED_BYTE
, pixels
);
179 context3d_
->drawArrays(GL_TRIANGLE_STRIP
, 0, 4);
181 context3d_
->prepareTexture();
184 } // namespace content