OLD | NEW |
| (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/common/gpu/media/rendering_helper.h" | |
6 | |
7 #import <Cocoa/Cocoa.h> | |
8 #import <OpenGL/CGLMacro.h> | |
9 | |
10 #include "base/mac/scoped_nsautorelease_pool.h" | |
11 #include "base/memory/scoped_nsobject.h" | |
12 #include "base/message_loop.h" | |
13 #include "base/synchronization/waitable_event.h" | |
14 | |
15 // Gets the pixel format to be used by the OpenGL view. | |
16 static scoped_nsobject<NSOpenGLPixelFormat> GetPixelFormat() { | |
17 NSOpenGLPixelFormatAttribute attributes[] = { | |
18 NSOpenGLPFAWindow, | |
19 NSOpenGLPFADoubleBuffer, | |
20 NSOpenGLPFAAccelerated, | |
21 NSOpenGLPFANoRecovery, | |
22 NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)32, | |
23 NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8, | |
24 NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24, | |
25 (NSOpenGLPixelFormatAttribute)0 | |
26 }; | |
27 return scoped_nsobject<NSOpenGLPixelFormat>( | |
28 [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]); | |
29 } | |
30 | |
31 // Gets the CGLContext from the given OpenGL view. | |
32 static CGLContextObj GetCGLContext(NSOpenGLView* gl_view) { | |
33 return static_cast<CGLContextObj>([[gl_view openGLContext] CGLContextObj]); | |
34 } | |
35 | |
36 // Sets up a view port for the OpenGL view. | |
37 static void SetupGLViewPort(NSOpenGLView* gl_view, int width, int height) { | |
38 CGLContextObj cgl_ctx = GetCGLContext(gl_view); | |
39 glViewport(0, 0, width, height); | |
40 glClearColor(1.0, 0.0, 0.0, 0.0); | |
41 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
42 [[gl_view openGLContext] flushBuffer]; | |
43 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
44 } | |
45 | |
46 // Draw the given texture to the OpenGL view. | |
47 static void DrawTexture(NSOpenGLView* gl_view, | |
48 GLuint texture_id, | |
49 bool suppress_swap_to_display) { | |
50 CGLContextObj cgl_ctx = GetCGLContext(gl_view); | |
51 [gl_view lockFocus]; | |
52 | |
53 GLfloat width = [gl_view bounds].size.width; | |
54 GLfloat height = [gl_view bounds].size.height; | |
55 | |
56 glEnable(GL_TEXTURE_RECTANGLE_ARB); | |
57 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id); | |
58 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | |
59 | |
60 glBegin(GL_QUADS); | |
61 glTexCoord2f(0.0, height); | |
62 glVertex3f(-1.0, -1.0, 0.0); | |
63 glTexCoord2f(width, height); | |
64 glVertex3f(1.0, -1.0, 0.0); | |
65 glTexCoord2f(width, 0.0); | |
66 glVertex3f(1.0, 1.0, 0.0); | |
67 glTexCoord2f(0.0, 0.0); | |
68 glVertex3f(-1.0, 1.0, 0.0); | |
69 glEnd(); | |
70 | |
71 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); | |
72 glDisable(GL_TEXTURE_RECTANGLE_ARB); | |
73 | |
74 if (!suppress_swap_to_display) | |
75 [[gl_view openGLContext] flushBuffer]; | |
76 [gl_view unlockFocus]; | |
77 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
78 } | |
79 | |
80 namespace content { | |
81 | |
82 class RenderingHelperMac : public RenderingHelper { | |
83 public: | |
84 RenderingHelperMac(); | |
85 virtual ~RenderingHelperMac(); | |
86 | |
87 // Implement RenderingHelper. | |
88 virtual void Initialize(bool suppress_swap_to_display, | |
89 int num_windows, | |
90 const std::vector<gfx::Size>& dimensions, | |
91 base::WaitableEvent* done) OVERRIDE; | |
92 virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE; | |
93 virtual void CreateTexture(int window_id, | |
94 uint32 texture_target, | |
95 GLuint* texture_id, | |
96 base::WaitableEvent* done) OVERRIDE; | |
97 virtual void RenderTexture(GLuint texture_id) OVERRIDE; | |
98 virtual void DeleteTexture(GLuint texture_id) OVERRIDE; | |
99 virtual void* GetGLContext() OVERRIDE; | |
100 virtual void* GetGLDisplay() OVERRIDE; | |
101 | |
102 private: | |
103 base::MessageLoop* message_loop_; | |
104 int width_; | |
105 int height_; | |
106 bool suppress_swap_to_display_; | |
107 scoped_nsobject<NSWindow> window_; | |
108 scoped_nsobject<NSOpenGLView> gl_view_; | |
109 base::mac::ScopedNSAutoreleasePool pool_; | |
110 }; | |
111 | |
112 // static | |
113 RenderingHelper* RenderingHelper::Create() { | |
114 return new RenderingHelperMac; | |
115 } | |
116 | |
117 // static | |
118 void RenderingHelper::InitializePlatform() { | |
119 // Initialize the Cocoa framework. | |
120 base::mac::ScopedNSAutoreleasePool pool_; | |
121 [NSApplication sharedApplication]; | |
122 } | |
123 | |
124 RenderingHelperMac::RenderingHelperMac() | |
125 : message_loop_(NULL), | |
126 width_(0), | |
127 height_(0), | |
128 suppress_swap_to_display_(false) { | |
129 } | |
130 | |
131 RenderingHelperMac::~RenderingHelperMac() { | |
132 CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor."; | |
133 } | |
134 | |
135 void RenderingHelperMac::Initialize( | |
136 bool suppress_swap_to_display, | |
137 int num_windows, | |
138 const std::vector<gfx::Size>& dimensions, | |
139 base::WaitableEvent* done) { | |
140 // Use width_ != 0 as a proxy for the class having already been | |
141 // Initialize()'d, and UnInitialize() before continuing. | |
142 if (width_) { | |
143 base::WaitableEvent done2(false, false); | |
144 UnInitialize(&done2); | |
145 done2.Wait(); | |
146 } | |
147 | |
148 // A separate window is created for each decoder. Since the Mac API | |
149 // only supports a single instance only one window should be created. | |
150 CHECK_EQ(num_windows, 1); | |
151 | |
152 // There should be only one window dimension as only one window is created. | |
153 CHECK_EQ(dimensions.size(), 1U); | |
154 width_ = dimensions[0].width(); | |
155 height_ = dimensions[0].height(); | |
156 suppress_swap_to_display_ = suppress_swap_to_display; | |
157 message_loop_ = base::MessageLoop::current(); | |
158 | |
159 // Create a window to host the OpenGL contents. | |
160 NSRect rect = NSMakeRect(0, 0, width_, height_); | |
161 window_.reset([[NSWindow alloc] | |
162 initWithContentRect:rect | |
163 styleMask:NSTitledWindowMask | |
164 backing:NSBackingStoreBuffered | |
165 defer:NO]); | |
166 [window_ center]; | |
167 [window_ makeKeyAndOrderFront:nil]; | |
168 | |
169 // Create an OpenGL view. | |
170 scoped_nsobject<NSOpenGLPixelFormat> pixel_format(GetPixelFormat()); | |
171 gl_view_.reset([[NSOpenGLView alloc] initWithFrame:rect | |
172 pixelFormat:pixel_format]); | |
173 [[window_ contentView] addSubview:gl_view_]; | |
174 SetupGLViewPort(gl_view_, width_, height_); | |
175 | |
176 done->Signal(); | |
177 } | |
178 | |
179 void RenderingHelperMac::UnInitialize(base::WaitableEvent* done) { | |
180 CHECK_EQ(base::MessageLoop::current(), message_loop_); | |
181 width_ = 0; | |
182 height_ = 0; | |
183 message_loop_ = NULL; | |
184 [window_ close]; | |
185 window_.reset(); | |
186 gl_view_.reset(); | |
187 done->Signal(); | |
188 } | |
189 | |
190 void RenderingHelperMac::CreateTexture(int window_id, | |
191 uint32 texture_target, | |
192 GLuint* texture_id, | |
193 base::WaitableEvent* done) { | |
194 CHECK_EQ(base::MessageLoop::current(), message_loop_); | |
195 CHECK_EQ(static_cast<uint32>(GL_TEXTURE_RECTANGLE_ARB), texture_target); | |
196 CGLContextObj cgl_ctx = GetCGLContext(gl_view_); | |
197 glGenTextures(1, texture_id); | |
198 CHECK_EQ(GL_NO_ERROR, static_cast<int>(glGetError())); | |
199 done->Signal(); | |
200 } | |
201 | |
202 void RenderingHelperMac::RenderTexture(GLuint texture_id) { | |
203 CHECK_EQ(base::MessageLoop::current(), message_loop_); | |
204 DrawTexture(gl_view_, texture_id, suppress_swap_to_display_); | |
205 } | |
206 | |
207 void RenderingHelperMac::DeleteTexture(GLuint texture_id) { | |
208 CHECK_EQ(base::MessageLoop::current(), message_loop_); | |
209 CGLContextObj cgl_ctx = GetCGLContext(gl_view_); | |
210 glDeleteTextures(1, &texture_id); | |
211 CHECK_EQ(GL_NO_ERROR, static_cast<int>(glGetError())); | |
212 } | |
213 | |
214 void* RenderingHelperMac::GetGLContext() { | |
215 return GetCGLContext(gl_view_); | |
216 } | |
217 | |
218 void* RenderingHelperMac::GetGLDisplay() { | |
219 return NULL; | |
220 } | |
221 | |
222 } // namespace content | |
OLD | NEW |