Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(518)

Side by Side Diff: content/browser/renderer_host/compositing_iosurface_mac.mm

Issue 9958100: Unobfuscate RWHVMac accelerated compositing code path by separating it from plugin code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: public APIs of CompositingIOSurface set context current Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "content/browser/renderer_host/compositing_iosurface_mac.h"
6
7 #include <OpenGL/OpenGL.h>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "ui/gfx/gl/gl_context.h"
15 #include "ui/gfx/gl/gl_switches.h"
16 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
17 #include "ui/gfx/surface/io_surface_support_mac.h"
18
19 #ifdef NDEBUG
20 #define CHECK_GL_ERROR()
21 #else
22 #define CHECK_GL_ERROR() do { \
23 GLenum gl_error = glGetError(); \
24 LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error :" << gl_error; \
25 } while (0)
26 #endif
27
28 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() {
29 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create");
30 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
31 if (!io_surface_support) {
32 LOG(WARNING) << "No IOSurface support";
33 return NULL;
34 }
35
36 std::vector<NSOpenGLPixelFormatAttribute> attributes;
37 attributes.push_back(NSOpenGLPFADoubleBuffer);
38 // We don't need a depth buffer - try setting its size to 0...
39 attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0);
40 if (gfx::GLContext::SupportsDualGpus())
41 attributes.push_back(NSOpenGLPFAAllowOfflineRenderers);
42 attributes.push_back(0);
43
44 scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat(
45 [[NSOpenGLPixelFormat alloc] initWithAttributes:&attributes.front()]);
46 if (!glPixelFormat) {
47 LOG(ERROR) << "NSOpenGLPixelFormat initWithAttributes failed";
48 return NULL;
49 }
50
51 scoped_nsobject<NSOpenGLContext> glContext(
52 [[NSOpenGLContext alloc] initWithFormat:glPixelFormat
53 shareContext:nil]);
54 if (!glContext) {
55 LOG(ERROR) << "NSOpenGLContext initWithFormat failed";
56 return NULL;
57 }
58
59 // We "punch a hole" in the window, and have the WindowServer render the
60 // OpenGL surface underneath so we can draw over it.
61 GLint belowWindow = -1;
62 [glContext setValues:&belowWindow forParameter:NSOpenGLCPSurfaceOrder];
63
64 CGLContextObj cglContext = (CGLContextObj)[glContext CGLContextObj];
65 if (!cglContext) {
66 LOG(ERROR) << "CGLContextObj failed";
67 return NULL;
68 }
69
70 // Draw at beam vsync.
71 GLint swapInterval;
72 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
73 swapInterval = 0;
74 else
75 swapInterval = 1;
76 [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
77
78 return new CompositingIOSurfaceMac(io_surface_support, glContext.release(),
79 cglContext);
80 }
81
82 CompositingIOSurfaceMac::CompositingIOSurfaceMac(
83 IOSurfaceSupport* io_surface_support,
84 NSOpenGLContext* glContext,
85 CGLContextObj cglContext)
86 : io_surface_support_(io_surface_support),
87 glContext_(glContext),
88 cglContext_(cglContext),
89 io_surface_handle_(0) {
90 }
91
92 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
93 UnrefIOSurface();
94 }
95
96 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle) {
97 CGLSetCurrentContext(cglContext_);
98 MapIOSurfaceToTexture(io_surface_handle);
99 CGLSetCurrentContext(0);
100 }
101
102 void CompositingIOSurfaceMac::DrawIOSurface(NSView* view) {
103 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::DrawIOSurface");
104 CGLSetCurrentContext(cglContext_);
105
106 bool has_io_surface = MapIOSurfaceToTexture(io_surface_handle_);
107
108 [glContext_ setView:view];
109 NSSize window_size = [view frame].size;
110 glViewport(0, 0, window_size.width, window_size.height);
111
112 glMatrixMode(GL_PROJECTION);
113 glLoadIdentity();
114 glOrtho(0, window_size.width, window_size.height, 0, -1, 1);
115 glMatrixMode(GL_MODELVIEW);
116 glLoadIdentity();
117
118 glDisable(GL_DEPTH_TEST);
119 glDisable(GL_BLEND);
120
121 glColorMask(true, true, true, true);
122 // Should match the clear color of RenderWidgetHostViewMac.
123 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
124 // TODO(jbates): Just clear the right and bottom edges when the size doesn't
125 // match the window. Then use a shader to blit the texture without its alpha
126 // channel.
127 glClear(GL_COLOR_BUFFER_BIT);
128
129 if (has_io_surface) {
130 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
131
132 // Draw only the color channels from the incoming texture.
133 glColorMask(true, true, true, false);
134
135 // Draw the color channels from the incoming texture.
136 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); CHECK_GL_ERROR();
137 glEnable(GL_TEXTURE_RECTANGLE_ARB); CHECK_GL_ERROR();
138
139 glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERROR();
140 glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_GL_ERROR();
141
142 glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad_.verts_[0].x_);
143 glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad_.verts_[0].tx_);
144 glDrawArrays(GL_QUADS, 0, 4); CHECK_GL_ERROR();
145
146 glDisableClientState(GL_VERTEX_ARRAY);
147 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
148
149 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_GL_ERROR();
150 }
151
152 CGLFlushDrawable(cglContext_);
153
154 CGLSetCurrentContext(0);
155 }
156
157 bool CompositingIOSurfaceMac::MapIOSurfaceToTexture(
158 uint64 io_surface_handle) {
159 if (io_surface_.get() && io_surface_handle == io_surface_handle_)
160 return true;
161
162 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture");
163 UnrefIOSurfaceWithContextCurrent();
164
165 io_surface_.reset(io_surface_support_->IOSurfaceLookup(
166 static_cast<uint32>(io_surface_handle)));
167 // Can fail if IOSurface with that ID was already released by the gpu
168 // process.
169 if (!io_surface_.get()) {
170 io_surface_handle_ = 0;
171 return false;
172 }
173
174 io_surface_handle_ = io_surface_handle;
175 io_surface_size_.SetSize(
176 io_surface_support_->IOSurfaceGetWidth(io_surface_),
177 io_surface_support_->IOSurfaceGetHeight(io_surface_));
178
179 quad_.set_size(io_surface_size_);
180
181 GLenum target = GL_TEXTURE_RECTANGLE_ARB;
182 glGenTextures(1, &texture_);
183 glBindTexture(target, texture_);
184 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
185 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); CHECK_GL_ERROR();
186 GLuint plane = 0;
187 CGLError cglerror =
188 io_surface_support_->CGLTexImageIOSurface2D(cglContext_,
189 target,
190 GL_RGBA,
191 io_surface_size_.width(),
192 io_surface_size_.height(),
193 GL_BGRA,
194 GL_UNSIGNED_INT_8_8_8_8_REV,
195 io_surface_.get(),
196 plane);
197 CHECK_GL_ERROR();
198 if (cglerror != kCGLNoError) {
199 LOG(ERROR) << "CGLTexImageIOSurface2D: " << cglerror;
200 return false;
201 }
202
203 return true;
204 }
205
206 void CompositingIOSurfaceMac::UnrefIOSurface() {
207 CGLSetCurrentContext(cglContext_);
208 UnrefIOSurfaceWithContextCurrent();
209 CGLSetCurrentContext(0);
210 }
211
212 void CompositingIOSurfaceMac::UnrefIOSurfaceWithContextCurrent() {
213 if (texture_) {
214 glDeleteTextures(1, &texture_);
215 texture_ = 0;
216 }
217
218 io_surface_.reset();
219 }
220
221 void CompositingIOSurfaceMac::GlobalFrameDidChange() {
222 [glContext_ update];
223 }
224
225 void CompositingIOSurfaceMac::ClearDrawable() {
226 [glContext_ clearDrawable];
227 UnrefIOSurface();
228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698