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

Side by Side Diff: ppapi/examples/video_decoder/video_decoder_session.cc

Issue 6961018: Pepper Video Decoder API tester plugin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More implementation meat and clearing things all around. Created 9 years, 6 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) 2011 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 "ppapi/examples/video_decoder/video_decoder_session.h"
6
7 #include <cstring>
8 #include <fstream>
9 #include <iostream>
10
11 #include "ppapi/c/dev/pp_graphics_3d_dev.h"
12 #include "ppapi/c/dev/ppb_buffer_dev.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/cpp/dev/context_3d_dev.h"
15 #include "ppapi/cpp/dev/surface_3d_dev.h"
16 #include "ppapi/cpp/dev/video_decoder_dev.h"
17 #include "ppapi/lib/gl/include/GLES2/gl2.h"
18
19 // Pull-based video source to read video data from a file.
20 class TestVideoSource {
21 public:
22 TestVideoSource()
23 : file_length_(0),
24 offset_(0) {}
25
26 ~TestVideoSource() {}
27
28 bool Open(const std::string& url) {
29 // TODO(vmr): Use file_util::ReadFileToString or equivalent to read the file
30 // if one-shot reading is used.
31 std::ifstream* file =
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 scoped_ptr, then delete the deletes below :)
Ville-Mikko Rautio 2011/06/03 13:24:39 I am in impression that relying on anything from C
32 new std::ifstream(url.c_str(),
33 std::ios::in | std::ios::binary | std::ios::ate);
34 if (!file->good()) {
35 delete file;
36 return false;
37 }
38 file->seekg(0, std::ios::end);
39 uint32_t length = file->tellg();
40 file->seekg(0, std::ios::beg);
41 mem_ = new uint8_t[length];
42 file->read(reinterpret_cast<char*>(mem_), length);
43 file_length_ = length;
44 file->close();
45 delete file;
46 return true;
47 }
48
49 // Reads next packet from the input stream.
50 // Returns number of read bytes on success, 0 on when there was no valid data
51 // to be read and -1 if user gave NULL or too small buffer.
52 // TODO(vmr): Modify to differentiate between errors and EOF.
53 int32_t Read(uint8_t* target_mem, uint32_t size) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 It looks like you are doing some decoding to split
Ville-Mikko Rautio 2011/06/03 13:24:39 There is possibility to pass the whole bitstream f
54 if (!target_mem)
55 return -1;
56 uint8_t* unit_begin = NULL;
57 uint8_t* unit_end = NULL;
58 uint8_t* ptr = mem_ + offset_;
59 while (offset_ + 4 < file_length_) {
60 if (ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 1) {
61 // start code found
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Complete sentence + explanation of start code.
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
62 if (!unit_begin) {
63 unit_begin = ptr;
64 } else {
65 // back-up 1 byte.
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Complete sentence.
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
66 unit_end = ptr;
67 break;
68 }
69 }
70 ptr++;
71 offset_++;
72 }
73 if (unit_begin && offset_ + 4 == file_length_) {
74 // Last unit. Set the unit_end to point to the last byte.
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 The last buffer begins _and_ ends with 0001? In ot
Ville-Mikko Rautio 2011/06/03 13:24:39 There's no 0001 at the end. +4 needed because of t
75 unit_end = ptr + 4;
76 offset_ += 4;
77 } else if (!unit_begin || !unit_end) {
78 // No unit start codes found in buffer.
79 return 0;
80 }
81 if (static_cast<int32_t>(size) >= unit_end - unit_begin) {
82 memcpy(target_mem, unit_begin, unit_end - unit_begin);
83 return unit_end - unit_begin;
84 }
85 // Rewind to the beginning start code if there is one as it should be
86 // returned with next Read().
87 offset_ = unit_begin - mem_;
88 return -1;
89 }
90
91 private:
92 uint32_t file_length_;
93 uint32_t offset_;
94 uint8_t* mem_;
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 scoped_array? At the very least you need to delete
Ville-Mikko Rautio 2011/06/03 13:24:39 True. Added delete for destructor since I am not s
95 };
96
97 LocalVideoBitstreamSource::LocalVideoBitstreamSource(std::string filename)
98 : file_(filename),
99 video_source_(new TestVideoSource()),
100 video_source_open_(false) {
101 }
102
103 LocalVideoBitstreamSource::~LocalVideoBitstreamSource() {
104 delete video_source_;
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 No longer needed w/ scoped_ptr
Ville-Mikko Rautio 2011/06/03 13:24:39 Ditto.
105 }
106
107 bool LocalVideoBitstreamSource::GetBitstreamUnit(
108 void* target_mem,
109 uint32_t target_mem_size_in_bytes,
110 int32_t* unit_size_in_bytes) {
111 if (!video_source_open_) {
112 if (!video_source_->Open(file_)) {
113 return false;
114 }
115 video_source_open_ = true;
116 }
117 int32_t read_bytes = video_source_->Read(static_cast<uint8_t*>(target_mem),
118 target_mem_size_in_bytes);
119 if (read_bytes <= 0) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: no {} for one-line condition
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
120 return false;
121 }
122 *unit_size_in_bytes = read_bytes;
123 return true;
124 }
125
126 VideoDecoderSessionClient::~VideoDecoderSessionClient() {
127 }
128
129 // Constants used by VideoDecoderSession.
130 static const int32_t kBitstreamBufferCount = 3;
131 static const int32_t kBitstreamBufferSize = 256 * 1024 * 1024;
132 static const int32_t kDefaultWidth = 640;
133 static const int32_t kDefaultHeight = 480;
134
135 bool VideoDecoderSession::Initialize(
136 const std::vector<uint32_t>& decoder_config,
137 pp::CompletionCallback completion_callback) {
138 assert(video_source_ && display_);
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Do this check in the constructor.
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
139 // Default implementation just assumes everything is set up.
140 if (!AllocateInputBuffers()) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: No {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
141 return false;
142 }
143 pp::CompletionCallback cb = cb_factory_.NewCallback(
144 &VideoDecoderSession::OnInitializeDone, completion_callback);
145 video_decoder_ = new pp::VideoDecoder(instance_, decoder_config, cb, this);
146 if (!video_decoder_) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: No {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
147 return false;
148 }
149 return true;
150 }
151
152 bool VideoDecoderSession::Run(pp::CompletionCallback completion_callback) {
153 assert(state_ == kInitialized);
154 // Start the streaming by dispatching the first buffers one by one.
155 for (std::map<int32_t, PP_VideoBitstreamBuffer_Dev>::iterator it =
156 bitstream_buffers_.begin();
157 it == bitstream_buffers_.end();
158 it++) {
159 if (!ReadAndDispatchBitstreamUnit((*it).first)) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
160 return false;
161 }
162 }
163 // Once streaming has been started, we're running.
164 ChangeState(kRunning);
165 completion_callback.Run(PP_OK);
166 return true;
167 }
168
169 bool VideoDecoderSession::Stop(pp::CompletionCallback completion_callback) {
170 assert(state_ == kRunning);
171 // Stop the playback.
172 ChangeState(kInitialized);
173 return true;
174 }
175
176 bool VideoDecoderSession::Flush(pp::CompletionCallback completion_callback) {
177 assert(state_ == kRunning);
178 // Issue the flush request.
179 ChangeState(kFlushing);
180 video_decoder_->Flush(cb_factory_.NewCallback(
181 &VideoDecoderSession::OnUserFlushDone, state_, completion_callback));
182 return true;
183 }
184
185 bool VideoDecoderSession::Teardown(pp::CompletionCallback completion_callback) {
186 assert(state_ == kInitialized);
187 // Teardown the resources.
188 FreeInputBuffers();
189 ChangeState(kCreated);
190 completion_callback.Run(PP_OK);
191 return true;
192 }
193
194 void VideoDecoderSession::ProvidePictureBuffers(
195 uint32_t requested_num_of_buffers,
196 const std::vector<uint32_t>& buffer_properties) {
vjain 2011/05/31 22:29:07 What is the purpose of buffer_properties? Will GPU
Ville-Mikko Rautio 2011/06/01 11:50:08 Buffer properties will contain width & height and
vrk (LEFT CHROMIUM) 2011/06/01 22:41:31 Actually, this C++ API is not up to date with the
Ville-Mikko Rautio 2011/06/03 13:24:39 C++ API change (http://codereview.chromium.org/708
197 // Currently we support only GLES buffer allocation.
198 std::vector<PP_GLESBuffer_Dev> buffers;
199 for (uint32_t i = 0; i < requested_num_of_buffers; i++) {
200 PP_GLESBuffer_Dev gles_buffer;
201 if (!display_->ProvideGLESPictureBuffer(buffer_properties, &gles_buffer)) {
202 video_decoder_->Abort(cb_factory_.NewCallback(
203 &VideoDecoderSession::OnAbortDone));
204 return;
205 }
206 buffers.push_back(gles_buffer);
207 }
208 video_decoder_->AssignGLESBuffers(buffers.size(), buffers);
209 }
210
211 void VideoDecoderSession::DismissPictureBuffer(int32_t picture_buffer_id) {
212 if (!display_->DismissPictureBuffer(picture_buffer_id)) {
213 assert(!"Failed to dismiss picture buffer properly");
214 return;
215 }
216 }
217
218 void VideoDecoderSession::PictureReady(const PP_Picture_Dev& picture) {
219 display_->DrawPicture(picture, cb_factory_.NewCallback(
220 &VideoDecoderSession::OnDrawPictureDone, picture.picture_buffer_id));
221 }
222
223 void VideoDecoderSession::NotifyEndOfStream() {
224 end_of_stream_ = true;
225 video_decoder_->Flush(cb_factory_.NewCallback(
226 &VideoDecoderSession::OnInternalFlushDone));
227 }
228
229 void VideoDecoderSession::NotifyError(PP_VideoDecodeError_Dev error) {
230 video_decoder_->Flush(cb_factory_.NewCallback(
231 &VideoDecoderSession::OnInternalFlushDone));
232 }
233
234 int32_t VideoDecoderSession::GetUniqueId() {
235 // Not exactly unique in the current form but close enough for use case.
236 return next_id_++;
237 }
238
239 void VideoDecoderSession::OnInitializeDone(int32_t result,
240 pp::CompletionCallback callback) {
241 if (state_ != kCreated) {
242 ChangeState(kCreated);
243 callback.Run(PP_ERROR_ABORTED);
244 }
245 if (result != PP_OK) {
246 ChangeState(kInitialized);
247 callback.Run(result);
248 }
249 callback.Run(PP_OK);
250 }
251
252 void VideoDecoderSession::OnBitstreamBufferProcessed(
vjain 2011/06/02 01:04:52 Hi Ville-Mikko, When the GPU decoder returns the b
Ville-Mikko Rautio 2011/06/03 13:24:39 I am not sure what are you referring to. Bitstream
253 int32_t result,
254 int32_t bitstream_buffer_id) {
255 // Reuse each bitstream buffer that has been processed by reading data into it
256 // as long as there is more and pass that for decoding.
257 ReadAndDispatchBitstreamUnit(bitstream_buffer_id);
258 }
259
260 void VideoDecoderSession::OnDrawPictureDone(int32_t result,
261 int32_t picture_buffer_id) {
262 video_decoder_->ReusePictureBuffer(picture_buffer_id);
263 }
264
265 void VideoDecoderSession::OnUserFlushDone(int32_t result,
266 State target_state,
267 pp::CompletionCallback callback) {
268 assert(state_ == kFlushing);
269 // It was a Flush request, return to the state where we started.
270 ChangeState(target_state);
271 callback.Run(result);
272 }
273
274 void VideoDecoderSession::OnInternalFlushDone(int32_t result) {
275 if (end_of_stream_) {
276 // It was end of stream flush.
277 video_decoder_->Abort(cb_factory_.NewCallback(
278 &VideoDecoderSession::OnAbortDone));
279 } else {
280 assert(!"Unhandled flush completion!");
281 }
282 }
283
284 void VideoDecoderSession::OnAbortDone(int32_t result) {
285 client_->OnSessionCompleted(result);
286 }
287
288 bool VideoDecoderSession::AllocateInputBuffers() {
289 buffer_if_ = static_cast<const struct PPB_Buffer_Dev*>(
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 ?? Why is this field being set here? Shouldn't thi
Ville-Mikko Rautio 2011/06/03 13:24:39 Moved to ctor and added assert for variable.
290 pp::Module::Get()->GetBrowserInterface(PPB_BUFFER_DEV_INTERFACE));
291 if (!buffer_if_) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Removed
292 return false;
293 }
294 // Allocate |kBitstreamBufferCount| bitstream buffers of
295 // |kBitstreamBufferSize| bytes.
296 for (int32_t i = 0; i < kBitstreamBufferCount; i++) {
297 PP_VideoBitstreamBuffer_Dev bitstream_buffer;
298 bitstream_buffer.data = buffer_if_->Create(instance_->pp_instance(),
299 kBitstreamBufferSize);
300 if (bitstream_buffer.data == 0) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
301 return false;
302 }
303 bitstream_buffer.size = 0;
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 This should be kBitstreamBufferSize with change me
Ville-Mikko Rautio 2011/06/03 13:24:39 This is the amount of valid data in buffer, so I d
304 bitstream_buffer.id = GetUniqueId();
305 bitstream_buffers_[bitstream_buffer.id] = bitstream_buffer;
306 }
307 return true;
308 }
309
310 void VideoDecoderSession::FreeInputBuffers() {
311 std::map<int32_t, PP_VideoBitstreamBuffer_Dev>::iterator it;
312 for (it = bitstream_buffers_.begin(); it != bitstream_buffers_.end(); it++) {
313 std::pair<int32_t, PP_VideoBitstreamBuffer_Dev> pair = *it;
314 PP_VideoBitstreamBuffer_Dev bitstream_buffer = pair.second;
315 pp::Module::Get()->core()->ReleaseResource(bitstream_buffer.data);
316 bitstream_buffers_.erase(it);
317 }
318 }
319
320 bool VideoDecoderSession::ReadAndDispatchBitstreamUnit(
321 int32_t bitstream_buffer_id) {
322 // Get the target memory and read the bitstream unit into it.
323 if (bitstream_buffers_.find(bitstream_buffer_id) ==
324 bitstream_buffers_.end()) {
325 return false;
326 }
327 PP_VideoBitstreamBuffer_Dev bitstream_buffer =
328 bitstream_buffers_[bitstream_buffer_id];
329 void* target_mem = buffer_if_->Map(bitstream_buffer.data);
330 if (target_mem == NULL) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
331 return false;
332 }
333 uint32_t size_in_bytes = 0;
334 if (!buffer_if_->Describe(bitstream_buffer.data, &size_in_bytes)) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
335 return false;
336 }
337 bool success = video_source_->GetBitstreamUnit(target_mem, size_in_bytes,
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 It's wasteful to allocate a buffer of kBitstreamBu
Ville-Mikko Rautio 2011/06/03 13:24:39 Already commented above. You cannot arbitrarily sp
338 &bitstream_buffer.size);
339 if (!success) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
340 return false;
341 }
342 // Dispatch the bitstream unit to the decoder.
343 success = video_decoder_->Decode(
344 bitstream_buffers_[bitstream_buffer_id],
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 bitstream_buffer?
Ville-Mikko Rautio 2011/06/03 13:24:39 Yep. Also, I changed the bitstream_buffer into ref
345 cb_factory_.NewCallback(
346 &VideoDecoderSession::OnBitstreamBufferProcessed,
347 bitstream_buffer_id));
348 // Finally unmap the buffer for this round.
349 buffer_if_->Unmap(bitstream_buffer.data);
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Unmap deletes the bitstream data. Shouldn't we onl
Ville-Mikko Rautio 2011/06/03 13:24:39 True. Done.
350 return success;
351 }
352
353 void VideoDecoderSession::ChangeState(State to_state) {
354 state_ = to_state;
355 }
356
357 int32_t VideoDecoderSession::next_id_ = 1;
358
359 // Pass-through vertex shader.
360 static const char kVertexShader[] =
361 "precision highp float; precision highp int;\n"
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 I don't believe these precision specifiers are nec
Ville-Mikko Rautio 2011/06/03 13:24:39 I am by no means shader expert, so I'll just take
362 "varying vec2 interp_tc;\n"
363 "\n"
364 "attribute vec4 in_pos;\n"
365 "attribute vec2 in_tc;\n"
366 "\n"
367 "void main() {\n"
368 " interp_tc = in_tc;\n"
369 " gl_Position = in_pos;\n"
370 "}\n";
371
372 // Color shader for EGLImage.
373 static const char kFragmentShaderEgl[] =
374 "precision mediump float;\n"
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Ditto above.
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
375 "precision mediump int;\n"
376 "varying vec2 interp_tc;\n"
377 "\n"
378 "uniform sampler2D tex;\n"
379 "\n"
380 "void main() {\n"
381 " gl_FragColor = texture2D(tex, interp_tc);\n"
382 "}\n";
383
384 // Buffer size for compile errors.
385 static const unsigned int kShaderErrorSize = 4096;
386
387 void GLES2Display::Graphics3DContextLost() {
388 assert(!"GLES2: Unexpectedly lost graphics context");
389 }
390
391 bool GLES2Display::Initialize() {
392 if (!InitGL(surface_size_.width, surface_size_.height)) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
393 return false;
394 }
395 ProgramShaders();
396 return true;
397 }
398
399 bool GLES2Display::ProvideGLESPictureBuffer(
400 const std::vector<uint32_t>& buffer_properties,
401 PP_GLESBuffer_Dev* picture_buffer) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Would make sense to also do the initial call to Te
Ville-Mikko Rautio 2011/06/03 13:24:39 I don't know GL well, so I will need your help in
402 GLuint texture;
403 // Generate texture and bind (effectively allocate) it.
404 gles2_if_->GenTextures(context_->pp_resource(), 1, &texture);
405 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture);
406 picture_buffer->context = 0; // TODO(vmr): Get proper context id.
407 picture_buffer->texture_id = texture;
408 picture_buffer->info.id = VideoDecoderSession::GetUniqueId();
409 picture_buffer->info.size.width = surface_size_.width;
410 picture_buffer->info.size.height = surface_size_.height;
411 // Store the values into the map for GLES buffers.
412 gles_buffers_[picture_buffer->info.id] = *picture_buffer;
413 assertNoGLError();
414 return true;
415 }
416
417 bool GLES2Display::DismissPictureBuffer(int32_t picture_buffer_id) {
418 gles2_if_->DeleteTextures(context_->pp_resource(), 1,
419 &gles_buffers_[picture_buffer_id].texture_id);
420 gles_buffers_.erase(picture_buffer_id);
421 return true;
422 }
423
424 bool GLES2Display::DrawPicture(const PP_Picture_Dev& picture,
425 pp::CompletionCallback completion_callback) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 nit: add space before pp
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
426 // Decoder has finished decoding picture into the texture, we'll have to just
427 // draw the texture to the color buffer and swap the surfaces.
428 // Clear the color buffer.
429 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT |
430 GL_DEPTH_BUFFER_BIT);
431 // Load the texture into texture unit 0.
432 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0);
433 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D,
434 gles_buffers_[picture.picture_buffer_id].texture_id);
435 // Draw the texture.
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 You never copy data into the texture (TexImage2D/M
Ville-Mikko Rautio 2011/06/03 13:24:39 See above comment about ProvideGLESPictureBuffer.
436 gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4);
437 // Force the execution of pending commands.
438 // TODO(vmr): Do we have to do this? Can we rely command buffer to execute the
439 // commands without Finish call?
440 gles2_if_->Finish(context_->pp_resource());
441 assertNoGLError();
442
443 int32_t error = surface_->SwapBuffers(completion_callback);
444 if (error != PP_OK) {
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 nit: no {}
Ville-Mikko Rautio 2011/06/03 13:24:39 Done.
445 return false;
446 }
447 assertNoGLError();
448 return true;
449 }
450
451 void GLES2Display::assertNoGLError() {
452 assert(!gles2_if_->GetError(context_->pp_resource()));
453 }
454
455 bool GLES2Display::InitGL(int width, int height) {
456 assert(width && height);
457 gles2_if_ = static_cast<const struct PPB_OpenGLES2_Dev*>(
458 pp::Module::Get()->GetBrowserInterface(PPB_OPENGLES2_DEV_INTERFACE));
459 // Firstly, we need OpenGL ES context associated with the display our plugin
460 // is rendering to.
461 if (context_) delete(context_);
462 context_ = new pp::Context3D_Dev(*instance_, 0, pp::Context3D_Dev(), NULL);
463 assert(!context_->is_null());
464 // Then we need surface bound to our fresh context. We'll be actually drawing
465 // on this surface and swapping that surface to refresh the displayable data
466 // of the plugin.
467 int32_t surface_attributes[] = {
468 PP_GRAPHICS3DATTRIB_WIDTH, surface_size_.width,
469 PP_GRAPHICS3DATTRIB_HEIGHT, surface_size_.height,
470 PP_GRAPHICS3DATTRIB_NONE
471 };
472 if (surface_) delete(surface_);
473 surface_ = new pp::Surface3D_Dev(*instance_, 0, surface_attributes);
474 assert(!surface_->is_null());
475 int32_t bind_error = context_->BindSurfaces(*surface_, *surface_);
476 if (!bind_error) {
477 assert(bind_error);
478 }
479 assertNoGLError();
480
481 bool success = instance_->BindGraphics(*surface_);
482 if (!success) {
483 assert(success);
484 }
485 // Clear the color buffer with opaque white for starters.
486 gles2_if_->ClearColor(context_->pp_resource(), 1.0, 1.0, 1.0, 0.0);
487 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT);
488 // Set the viewport to match the whole GL window.
489 gles2_if_->Viewport(context_->pp_resource(), 0, 0, surface_size_.width,
490 surface_size_.height);
491 assertNoGLError();
492 return true;
493 }
494
495 void GLES2Display::CreateShader(GLuint program, GLenum type,
496 const char* source,
497 int size) {
498 GLuint shader = gles2_if_->CreateShader(context_->pp_resource(), type);
499 gles2_if_->ShaderSource(
500 context_->pp_resource(), shader, 1, &source, &size);
501 gles2_if_->CompileShader(context_->pp_resource(), shader);
502
503 int result = GL_FALSE;
504 gles2_if_->GetShaderiv(
505 context_->pp_resource(), shader, GL_COMPILE_STATUS, &result);
506 if (!result) {
507 char log[kShaderErrorSize];
508 int len = 0;
509 gles2_if_->GetShaderInfoLog(context_->pp_resource(), shader,
510 kShaderErrorSize - 1, &len, log);
511 log[len] = 0;
512 assert(result);
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 You never use log... change to fail with "log" as
Ville-Mikko Rautio 2011/06/03 13:24:39 In Pepper code?
513 }
514 gles2_if_->AttachShader(context_->pp_resource(), program, shader);
515 gles2_if_->DeleteShader(context_->pp_resource(), shader);
516 }
517
518 void GLES2Display::LinkProgram(const PPB_OpenGLES2_Dev* gles2_if_ ) {
519 gles2_if_->LinkProgram(context_->pp_resource(), program_);
520 int result = GL_FALSE;
521 gles2_if_->GetProgramiv(context_->pp_resource(), program_, GL_LINK_STATUS,
522 &result);
523 if (!result) {
524 char log[kShaderErrorSize];
525 int len = 0;
526 gles2_if_->GetProgramInfoLog(context_->pp_resource(), program_,
527 kShaderErrorSize - 1, &len, log);
528 log[len] = 0;
529 assert(result);
530 }
531 gles2_if_->UseProgram(context_->pp_resource(), program_);
532 }
533
534 void GLES2Display::ProgramShaders() {
535 // Vertices for a full screen quad.
536 static const float kVertices[] = {
537 -1.f, 1.f,
538 -1.f, -1.f,
539 1.f, 1.f,
540 1.f, -1.f,
541 };
542
543 // Texture Coordinates mapping the entire texture for EGL image.
544 static const float kTextureCoordsEgl[] = {
545 0, 1,
546 0, 0,
547 1, 1,
548 1, 0,
549 };
550 program_ = gles2_if_->CreateProgram(context_->pp_resource());
551
552 // Create shader for EGL image
553 CreateShader(program_, GL_VERTEX_SHADER,
554 kVertexShader, sizeof(kVertexShader));
555 CreateShader(program_, GL_FRAGMENT_SHADER,
556 kFragmentShaderEgl, sizeof(kFragmentShaderEgl));
557 LinkProgram(gles2_if_);
558
559 assertNoGLError();
560 // Bind parameters.
561 gles2_if_->Uniform1i(context_->pp_resource(), gles2_if_->
562 GetUniformLocation(context_->pp_resource(), program_,
563 "tex"), 0);
564 gles2_if_->GenBuffers(context_->pp_resource(), 1, &vertex_buffer_);
565 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER,
566 vertex_buffer_);
567 gles2_if_->BufferData(context_->pp_resource(), GL_ARRAY_BUFFER,
568 8 * sizeof(kVertices[0]), kVertices, GL_STREAM_DRAW);
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Should this be GL_STATIC_DRAW?
Ville-Mikko Rautio 2011/06/03 13:24:39 I think both will work. I took your suggestion. Do
569
570 assertNoGLError();
571 int pos_location = gles2_if_->GetAttribLocation(context_->pp_resource(),
572 program_, "in_pos");
573 gles2_if_->EnableVertexAttribArray(context_->pp_resource(), pos_location);
574 gles2_if_->VertexAttribPointer(context_->pp_resource(), pos_location, 2,
575 GL_FLOAT, GL_FALSE, 0, 0);
576
577 assertNoGLError();
578 gles2_if_->GenBuffers(context_->pp_resource(), 1, &fragment_buffer_);
579 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER,
580 fragment_buffer_);
581 gles2_if_->BufferData(context_->pp_resource(), GL_ARRAY_BUFFER,
582 8 * sizeof(kTextureCoordsEgl[0]),
583 kTextureCoordsEgl, GL_STREAM_DRAW);
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 Ditto above.
Ville-Mikko Rautio 2011/06/03 13:24:39 Ditto.
584 assertNoGLError();
585 int tc_location = gles2_if_->GetAttribLocation(context_->pp_resource(),
586 program_, "in_tc");
587 gles2_if_->EnableVertexAttribArray(context_->pp_resource(), tc_location);
588 gles2_if_->VertexAttribPointer(context_->pp_resource(), tc_location, 2,
589 GL_FLOAT, GL_FALSE, 0, kTextureCoordsEgl);
590 gles2_if_->VertexAttribPointer(context_->pp_resource(), tc_location, 2,
591 GL_FLOAT, GL_FALSE, 0, 0);
592 gles2_if_->Enable(context_->pp_resource(), GL_DEPTH_TEST);
vrk (LEFT CHROMIUM) 2011/06/02 01:47:02 What is GL_DEPTH_TEST?
Ville-Mikko Rautio 2011/06/03 13:24:39 I believe it is feature of the fragment pipeline i
593 assertNoGLError();
594 }
595
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698