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

Side by Side Diff: ppapi/examples/gles2/gles2.cc

Issue 9620024: Move ppapi/examples/gles2/ to ppapi/examples/video_decode (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 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 <string.h>
6
7 #include <iostream>
8 #include <sstream>
9 #include <list>
10 #include <map>
11 #include <set>
12 #include <vector>
13
14 #include "ppapi/c/dev/ppb_console_dev.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/ppb_opengles2.h"
17 #include "ppapi/cpp/dev/video_decoder_client_dev.h"
18 #include "ppapi/cpp/dev/video_decoder_dev.h"
19 #include "ppapi/cpp/graphics_3d.h"
20 #include "ppapi/cpp/graphics_3d_client.h"
21 #include "ppapi/cpp/instance.h"
22 #include "ppapi/cpp/module.h"
23 #include "ppapi/cpp/rect.h"
24 #include "ppapi/cpp/var.h"
25 #include "ppapi/examples/gles2/testdata.h"
26 #include "ppapi/lib/gl/include/GLES2/gl2.h"
27 #include "ppapi/utility/completion_callback_factory.h"
28
29 // Use assert as a poor-man's CHECK, even in non-debug mode.
30 // Since <assert.h> redefines assert on every inclusion (it doesn't use
31 // include-guards), make sure this is the last file #include'd in this file.
32 #undef NDEBUG
33 #include <assert.h>
34
35 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a
36 // function to preserve line number information in the failure message.
37 #define assertNoGLError() \
38 assert(!gles2_if_->GetError(context_->pp_resource()));
39
40 namespace {
41
42 class GLES2DemoInstance : public pp::Instance,
43 public pp::Graphics3DClient,
44 public pp::VideoDecoderClient_Dev {
45 public:
46 GLES2DemoInstance(PP_Instance instance, pp::Module* module);
47 virtual ~GLES2DemoInstance();
48
49 // pp::Instance implementation (see PPP_Instance).
50 virtual void DidChangeView(const pp::Rect& position,
51 const pp::Rect& clip_ignored);
52
53 // pp::Graphics3DClient implementation.
54 virtual void Graphics3DContextLost() {
55 // TODO(vrk/fischman): Properly reset after a lost graphics context. In
56 // particular need to delete context_ and re-create textures.
57 // Probably have to recreate the decoder from scratch, because old textures
58 // can still be outstanding in the decoder!
59 assert(!"Unexpectedly lost graphics context");
60 }
61
62 // pp::VideoDecoderClient_Dev implementation.
63 virtual void ProvidePictureBuffers(PP_Resource decoder,
64 uint32_t req_num_of_bufs,
65 const PP_Size& dimensions);
66 virtual void DismissPictureBuffer(PP_Resource decoder,
67 int32_t picture_buffer_id);
68 virtual void PictureReady(PP_Resource decoder, const PP_Picture_Dev& picture);
69 virtual void NotifyError(PP_Resource decoder, PP_VideoDecodeError_Dev error);
70
71 private:
72 enum { kNumConcurrentDecodes = 7,
73 kNumDecoders = 2 }; // Baked into viewport rendering.
74
75 // A single decoder's client interface.
76 class DecoderClient {
77 public:
78 DecoderClient(GLES2DemoInstance* gles2, pp::VideoDecoder_Dev* decoder);
79 ~DecoderClient();
80
81 void DecodeNextNALUs();
82
83 // Per-decoder implementation of part of pp::VideoDecoderClient_Dev.
84 void ProvidePictureBuffers(uint32_t req_num_of_bufs,
85 PP_Size dimensions);
86 void DismissPictureBuffer(int32_t picture_buffer_id);
87
88 const PP_PictureBuffer_Dev& GetPictureBufferById(int id);
89 pp::VideoDecoder_Dev* decoder() { return decoder_; }
90
91 private:
92 void DecodeNextNALU();
93 static void GetNextNALUBoundary(size_t start_pos, size_t* end_pos);
94 void DecoderBitstreamDone(int32_t result, int bitstream_buffer_id);
95 void DecoderFlushDone(int32_t result);
96
97 GLES2DemoInstance* gles2_;
98 pp::VideoDecoder_Dev* decoder_;
99 pp::CompletionCallbackFactory<DecoderClient> callback_factory_;
100 int next_picture_buffer_id_;
101 int next_bitstream_buffer_id_;
102 size_t encoded_data_next_pos_to_decode_;
103 std::set<int> bitstream_ids_at_decoder_;
104 // Map of texture buffers indexed by buffer id.
105 typedef std::map<int, PP_PictureBuffer_Dev> PictureBufferMap;
106 PictureBufferMap picture_buffers_by_id_;
107 // Map of bitstream buffers indexed by id.
108 typedef std::map<int, pp::Buffer_Dev*> BitstreamBufferMap;
109 BitstreamBufferMap bitstream_buffers_by_id_;
110 };
111
112 // Initialize Video Decoders.
113 void InitializeDecoders();
114
115 // GL-related functions.
116 void InitGL();
117 GLuint CreateTexture(int32_t width, int32_t height);
118 void CreateGLObjects();
119 void CreateShader(GLuint program, GLenum type, const char* source, int size);
120 void DeleteTexture(GLuint id);
121 void PaintFinished(int32_t result, PP_Resource decoder,
122 int picture_buffer_id);
123
124 // Log an error to the developer console and stderr (though the latter may be
125 // closed due to sandboxing or blackholed for other reasons) by creating a
126 // temporary of this type and streaming to it. Example usage:
127 // LogError(this).s() << "Hello world: " << 42;
128 class LogError {
129 public:
130 LogError(GLES2DemoInstance* demo) : demo_(demo) {}
131 ~LogError() {
132 const std::string& msg = stream_.str();
133 demo_->console_if_->Log(demo_->pp_instance(), PP_LOGLEVEL_ERROR,
134 pp::Var(msg).pp_var());
135 std::cerr << msg << std::endl;
136 }
137 // Impl note: it would have been nicer to have LogError derive from
138 // std::ostringstream so that it can be streamed to directly, but lookup
139 // rules turn streamed string literals to hex pointers on output.
140 std::ostringstream& s() { return stream_; }
141 private:
142 GLES2DemoInstance* demo_; // Unowned.
143 std::ostringstream stream_;
144 };
145
146 pp::Size plugin_size_;
147 bool is_painting_;
148 // When decode outpaces render, we queue up decoded pictures for later
149 // painting. Elements are <decoder,picture>.
150 std::list<std::pair<PP_Resource, PP_Picture_Dev> > pictures_pending_paint_;
151 int num_frames_rendered_;
152 PP_TimeTicks first_frame_delivered_ticks_;
153 PP_TimeTicks last_swap_request_ticks_;
154 PP_TimeTicks swap_ticks_;
155 pp::CompletionCallbackFactory<GLES2DemoInstance> callback_factory_;
156
157 // Unowned pointers.
158 const PPB_Console_Dev* console_if_;
159 const PPB_Core* core_if_;
160 const PPB_OpenGLES2* gles2_if_;
161
162 // Owned data.
163 pp::Graphics3D* context_;
164 typedef std::map<int, DecoderClient*> Decoders;
165 Decoders video_decoders_;
166 };
167
168 GLES2DemoInstance::DecoderClient::DecoderClient(GLES2DemoInstance* gles2,
169 pp::VideoDecoder_Dev* decoder)
170 : gles2_(gles2), decoder_(decoder), callback_factory_(this),
171 next_picture_buffer_id_(0),
172 next_bitstream_buffer_id_(0), encoded_data_next_pos_to_decode_(0) {
173 }
174
175 GLES2DemoInstance::DecoderClient::~DecoderClient() {
176 delete decoder_;
177 decoder_ = NULL;
178
179 for (BitstreamBufferMap::iterator it = bitstream_buffers_by_id_.begin();
180 it != bitstream_buffers_by_id_.end(); ++it) {
181 delete it->second;
182 }
183 bitstream_buffers_by_id_.clear();
184
185 for (PictureBufferMap::iterator it = picture_buffers_by_id_.begin();
186 it != picture_buffers_by_id_.end(); ++it) {
187 gles2_->DeleteTexture(it->second.texture_id);
188 }
189 picture_buffers_by_id_.clear();
190 }
191
192 GLES2DemoInstance::GLES2DemoInstance(PP_Instance instance, pp::Module* module)
193 : pp::Instance(instance), pp::Graphics3DClient(this),
194 pp::VideoDecoderClient_Dev(this),
195 num_frames_rendered_(0),
196 first_frame_delivered_ticks_(-1),
197 swap_ticks_(0),
198 callback_factory_(this),
199 context_(NULL) {
200 assert((console_if_ = static_cast<const PPB_Console_Dev*>(
201 module->GetBrowserInterface(PPB_CONSOLE_DEV_INTERFACE))));
202 assert((core_if_ = static_cast<const PPB_Core*>(
203 module->GetBrowserInterface(PPB_CORE_INTERFACE))));
204 assert((gles2_if_ = static_cast<const PPB_OpenGLES2*>(
205 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE))));
206 }
207
208 GLES2DemoInstance::~GLES2DemoInstance() {
209 for (Decoders::iterator it = video_decoders_.begin();
210 it != video_decoders_.end(); ++it) {
211 delete it->second;
212 }
213 video_decoders_.clear();
214 delete context_;
215 }
216
217 void GLES2DemoInstance::DidChangeView(
218 const pp::Rect& position, const pp::Rect& clip_ignored) {
219 if (position.width() == 0 || position.height() == 0)
220 return;
221 if (plugin_size_.width()) {
222 assert(position.size() == plugin_size_);
223 return;
224 }
225 plugin_size_ = position.size();
226
227 // Initialize graphics.
228 InitGL();
229 InitializeDecoders();
230 }
231
232 void GLES2DemoInstance::InitializeDecoders() {
233 assert(video_decoders_.empty());
234 for (int i = 0; i < kNumDecoders; ++i) {
235 DecoderClient* client = new DecoderClient(
236 this, new pp::VideoDecoder_Dev(
237 this, *context_, PP_VIDEODECODER_H264PROFILE_BASELINE));
238 assert(!client->decoder()->is_null());
239 assert(video_decoders_.insert(std::make_pair(
240 client->decoder()->pp_resource(), client)).second);
241 client->DecodeNextNALUs();
242 }
243 }
244
245 void GLES2DemoInstance::DecoderClient::DecoderBitstreamDone(
246 int32_t result, int bitstream_buffer_id) {
247 assert(bitstream_ids_at_decoder_.erase(bitstream_buffer_id) == 1);
248 BitstreamBufferMap::iterator it =
249 bitstream_buffers_by_id_.find(bitstream_buffer_id);
250 assert(it != bitstream_buffers_by_id_.end());
251 delete it->second;
252 bitstream_buffers_by_id_.erase(it);
253 DecodeNextNALUs();
254 }
255
256 void GLES2DemoInstance::DecoderClient::DecoderFlushDone(int32_t result) {
257 assert(result == PP_OK);
258 // Check that each bitstream buffer ID we handed to the decoder got handed
259 // back to us.
260 assert(bitstream_ids_at_decoder_.empty());
261 delete decoder_;
262 decoder_ = NULL;
263 }
264
265 static bool LookingAtNAL(const unsigned char* encoded, size_t pos) {
266 return pos + 3 < kDataLen &&
267 encoded[pos] == 0 && encoded[pos + 1] == 0 &&
268 encoded[pos + 2] == 0 && encoded[pos + 3] == 1;
269 }
270
271 void GLES2DemoInstance::DecoderClient::GetNextNALUBoundary(
272 size_t start_pos, size_t* end_pos) {
273 assert(LookingAtNAL(kData, start_pos));
274 *end_pos = start_pos;
275 *end_pos += 4;
276 while (*end_pos + 3 < kDataLen &&
277 !LookingAtNAL(kData, *end_pos)) {
278 ++*end_pos;
279 }
280 if (*end_pos + 3 >= kDataLen) {
281 *end_pos = kDataLen;
282 return;
283 }
284 }
285
286 void GLES2DemoInstance::DecoderClient::DecodeNextNALUs() {
287 while (encoded_data_next_pos_to_decode_ <= kDataLen &&
288 bitstream_ids_at_decoder_.size() < kNumConcurrentDecodes) {
289 DecodeNextNALU();
290 }
291 }
292
293 void GLES2DemoInstance::DecoderClient::DecodeNextNALU() {
294 if (encoded_data_next_pos_to_decode_ == kDataLen) {
295 ++encoded_data_next_pos_to_decode_;
296 pp::CompletionCallback cb = callback_factory_.NewCallback(
297 &GLES2DemoInstance::DecoderClient::DecoderFlushDone);
298 decoder_->Flush(cb);
299 return;
300 }
301 size_t start_pos = encoded_data_next_pos_to_decode_;
302 size_t end_pos;
303 GetNextNALUBoundary(start_pos, &end_pos);
304 pp::Buffer_Dev* buffer = new pp::Buffer_Dev(gles2_, end_pos - start_pos);
305 PP_VideoBitstreamBuffer_Dev bitstream_buffer;
306 int id = ++next_bitstream_buffer_id_;
307 bitstream_buffer.id = id;
308 bitstream_buffer.size = end_pos - start_pos;
309 bitstream_buffer.data = buffer->pp_resource();
310 memcpy(buffer->data(), kData + start_pos, end_pos - start_pos);
311 assert(bitstream_buffers_by_id_.insert(std::make_pair(id, buffer)).second);
312
313 pp::CompletionCallback cb =
314 callback_factory_.NewCallback(
315 &GLES2DemoInstance::DecoderClient::DecoderBitstreamDone, id);
316 assert(bitstream_ids_at_decoder_.insert(id).second);
317 encoded_data_next_pos_to_decode_ = end_pos;
318 decoder_->Decode(bitstream_buffer, cb);
319 }
320
321 void GLES2DemoInstance::ProvidePictureBuffers(
322 PP_Resource decoder, uint32_t req_num_of_bufs, const PP_Size& dimensions) {
323 DecoderClient* client = video_decoders_[decoder];
324 assert(client);
325 client->ProvidePictureBuffers(req_num_of_bufs, dimensions);
326 }
327
328 void GLES2DemoInstance::DecoderClient::ProvidePictureBuffers(
329 uint32_t req_num_of_bufs, PP_Size dimensions) {
330 std::vector<PP_PictureBuffer_Dev> buffers;
331 for (uint32_t i = 0; i < req_num_of_bufs; ++i) {
332 PP_PictureBuffer_Dev buffer;
333 buffer.size = dimensions;
334 buffer.texture_id =
335 gles2_->CreateTexture(dimensions.width, dimensions.height);
336 int id = ++next_picture_buffer_id_;
337 buffer.id = id;
338 buffers.push_back(buffer);
339 assert(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second);
340 }
341 decoder_->AssignPictureBuffers(buffers);
342 }
343
344 const PP_PictureBuffer_Dev&
345 GLES2DemoInstance::DecoderClient::GetPictureBufferById(
346 int id) {
347 PictureBufferMap::iterator it = picture_buffers_by_id_.find(id);
348 assert(it != picture_buffers_by_id_.end());
349 return it->second;
350 }
351
352 void GLES2DemoInstance::DismissPictureBuffer(PP_Resource decoder,
353 int32_t picture_buffer_id) {
354 DecoderClient* client = video_decoders_[decoder];
355 assert(client);
356 client->DismissPictureBuffer(picture_buffer_id);
357 }
358
359 void GLES2DemoInstance::DecoderClient::DismissPictureBuffer(
360 int32_t picture_buffer_id) {
361 gles2_->DeleteTexture(GetPictureBufferById(picture_buffer_id).texture_id);
362 picture_buffers_by_id_.erase(picture_buffer_id);
363 }
364
365 void GLES2DemoInstance::PictureReady(PP_Resource decoder,
366 const PP_Picture_Dev& picture) {
367 if (first_frame_delivered_ticks_ == -1)
368 assert((first_frame_delivered_ticks_ = core_if_->GetTimeTicks()) != -1);
369 if (is_painting_) {
370 pictures_pending_paint_.push_back(std::make_pair(decoder, picture));
371 return;
372 }
373 DecoderClient* client = video_decoders_[decoder];
374 assert(client);
375 const PP_PictureBuffer_Dev& buffer =
376 client->GetPictureBufferById(picture.picture_buffer_id);
377 assert(!is_painting_);
378 is_painting_ = true;
379 int x = 0;
380 int y = 0;
381 if (client != video_decoders_.begin()->second) {
382 x = plugin_size_.width() / kNumDecoders;
383 y = plugin_size_.height() / kNumDecoders;
384 }
385
386 gles2_if_->Viewport(context_->pp_resource(), x, y,
387 plugin_size_.width() / kNumDecoders,
388 plugin_size_.height() / kNumDecoders);
389 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0);
390 gles2_if_->BindTexture(
391 context_->pp_resource(), GL_TEXTURE_2D, buffer.texture_id);
392 gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4);
393 pp::CompletionCallback cb =
394 callback_factory_.NewCallback(
395 &GLES2DemoInstance::PaintFinished, decoder, buffer.id);
396 last_swap_request_ticks_ = core_if_->GetTimeTicks();
397 assert(context_->SwapBuffers(cb) == PP_OK_COMPLETIONPENDING);
398 }
399
400 void GLES2DemoInstance::NotifyError(PP_Resource decoder,
401 PP_VideoDecodeError_Dev error) {
402 LogError(this).s() << "Received error: " << error;
403 assert(!"Unexpected error; see stderr for details");
404 }
405
406 // This object is the global object representing this plugin library as long
407 // as it is loaded.
408 class GLES2DemoModule : public pp::Module {
409 public:
410 GLES2DemoModule() : pp::Module() {}
411 virtual ~GLES2DemoModule() {}
412
413 virtual pp::Instance* CreateInstance(PP_Instance instance) {
414 return new GLES2DemoInstance(instance, this);
415 }
416 };
417
418 void GLES2DemoInstance::InitGL() {
419 assert(plugin_size_.width() && plugin_size_.height());
420 is_painting_ = false;
421
422 assert(!context_);
423 int32_t context_attributes[] = {
424 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
425 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
426 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
427 PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
428 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
429 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
430 PP_GRAPHICS3DATTRIB_SAMPLES, 0,
431 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
432 PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(),
433 PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(),
434 PP_GRAPHICS3DATTRIB_NONE,
435 };
436 context_ = new pp::Graphics3D(this, context_attributes);
437 assert(!context_->is_null());
438 assert(BindGraphics(*context_));
439
440 // Clear color bit.
441 gles2_if_->ClearColor(context_->pp_resource(), 1, 0, 0, 1);
442 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT);
443
444 assertNoGLError();
445
446 CreateGLObjects();
447 }
448
449 void GLES2DemoInstance::PaintFinished(int32_t result, PP_Resource decoder,
450 int picture_buffer_id) {
451 assert(result == PP_OK);
452 swap_ticks_ += core_if_->GetTimeTicks() - last_swap_request_ticks_;
453 is_painting_ = false;
454 ++num_frames_rendered_;
455 if (num_frames_rendered_ % 50 == 0) {
456 double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_;
457 double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000;
458 double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_;
459 LogError(this).s() << "Rendered frames: " << num_frames_rendered_
460 << ", fps: " << fps << ", with average ms/swap of: "
461 << ms_per_swap;
462 }
463 DecoderClient* client = video_decoders_[decoder];
464 if (client && client->decoder())
465 client->decoder()->ReusePictureBuffer(picture_buffer_id);
466 if (!pictures_pending_paint_.empty()) {
467 std::pair<PP_Resource, PP_Picture_Dev> decoder_picture =
468 pictures_pending_paint_.front();
469 pictures_pending_paint_.pop_front();
470 PictureReady(decoder_picture.first, decoder_picture.second);
471 }
472 }
473
474 GLuint GLES2DemoInstance::CreateTexture(int32_t width, int32_t height) {
475 GLuint texture_id;
476 gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id);
477 assertNoGLError();
478 // Assign parameters.
479 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0);
480 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id);
481 gles2_if_->TexParameteri(
482 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
483 GL_NEAREST);
484 gles2_if_->TexParameteri(
485 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
486 GL_NEAREST);
487 gles2_if_->TexParameterf(
488 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
489 GL_CLAMP_TO_EDGE);
490 gles2_if_->TexParameterf(
491 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
492 GL_CLAMP_TO_EDGE);
493
494 gles2_if_->TexImage2D(
495 context_->pp_resource(), GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
496 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
497 assertNoGLError();
498 return texture_id;
499 }
500
501 void GLES2DemoInstance::DeleteTexture(GLuint id) {
502 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &id);
503 }
504
505 void GLES2DemoInstance::CreateGLObjects() {
506 // Code and constants for shader.
507 static const char kVertexShader[] =
508 "varying vec2 v_texCoord; \n"
509 "attribute vec4 a_position; \n"
510 "attribute vec2 a_texCoord; \n"
511 "void main() \n"
512 "{ \n"
513 " v_texCoord = a_texCoord; \n"
514 " gl_Position = a_position; \n"
515 "}";
516
517 static const char kFragmentShader[] =
518 "precision mediump float; \n"
519 "varying vec2 v_texCoord; \n"
520 "uniform sampler2D s_texture; \n"
521 "void main() \n"
522 "{"
523 " gl_FragColor = texture2D(s_texture, v_texCoord); \n"
524 "}";
525
526 // Create shader program.
527 GLuint program = gles2_if_->CreateProgram(context_->pp_resource());
528 CreateShader(program, GL_VERTEX_SHADER, kVertexShader, sizeof(kVertexShader));
529 CreateShader(
530 program, GL_FRAGMENT_SHADER, kFragmentShader, sizeof(kFragmentShader));
531 gles2_if_->LinkProgram(context_->pp_resource(), program);
532 gles2_if_->UseProgram(context_->pp_resource(), program);
533 gles2_if_->DeleteProgram(context_->pp_resource(), program);
534 gles2_if_->Uniform1i(
535 context_->pp_resource(),
536 gles2_if_->GetUniformLocation(
537 context_->pp_resource(), program, "s_texture"), 0);
538 assertNoGLError();
539
540 // Assign vertex positions and texture coordinates to buffers for use in
541 // shader program.
542 static const float kVertices[] = {
543 -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates.
544 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates.
545 };
546
547 GLuint buffer;
548 gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer);
549 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer);
550 gles2_if_->BufferData(context_->pp_resource(), GL_ARRAY_BUFFER,
551 sizeof(kVertices), kVertices, GL_STATIC_DRAW);
552 assertNoGLError();
553 GLint pos_location = gles2_if_->GetAttribLocation(
554 context_->pp_resource(), program, "a_position");
555 GLint tc_location = gles2_if_->GetAttribLocation(
556 context_->pp_resource(), program, "a_texCoord");
557 assertNoGLError();
558 gles2_if_->EnableVertexAttribArray(context_->pp_resource(), pos_location);
559 gles2_if_->VertexAttribPointer(context_->pp_resource(), pos_location, 2,
560 GL_FLOAT, GL_FALSE, 0, 0);
561 gles2_if_->EnableVertexAttribArray(context_->pp_resource(), tc_location);
562 gles2_if_->VertexAttribPointer(
563 context_->pp_resource(), tc_location, 2, GL_FLOAT, GL_FALSE, 0,
564 static_cast<float*>(0) + 8); // Skip position coordinates.
565 assertNoGLError();
566 }
567
568 void GLES2DemoInstance::CreateShader(
569 GLuint program, GLenum type, const char* source, int size) {
570 GLuint shader = gles2_if_->CreateShader(context_->pp_resource(), type);
571 gles2_if_->ShaderSource(context_->pp_resource(), shader, 1, &source, &size);
572 gles2_if_->CompileShader(context_->pp_resource(), shader);
573 gles2_if_->AttachShader(context_->pp_resource(), program, shader);
574 gles2_if_->DeleteShader(context_->pp_resource(), shader);
575 }
576 } // anonymous namespace
577
578 namespace pp {
579 // Factory function for your specialization of the Module object.
580 Module* CreateModule() {
581 return new GLES2DemoModule();
582 }
583 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698