Index: ppapi/examples/video_decode/video_decode.cc |
diff --git a/ppapi/examples/video_decode/video_decode.cc b/ppapi/examples/video_decode/video_decode.cc |
index 6e4f4e18809dbc09cf97deaead6d69546e1a7c02..4e3354ae2bd9986472c2e99a3fadf1c5c3e01c66 100644 |
--- a/ppapi/examples/video_decode/video_decode.cc |
+++ b/ppapi/examples/video_decode/video_decode.cc |
@@ -24,6 +24,7 @@ |
#include "ppapi/cpp/var.h" |
#include "ppapi/examples/video_decode/testdata.h" |
#include "ppapi/lib/gl/include/GLES2/gl2.h" |
+#include "ppapi/lib/gl/include/GLES2/gl2ext.h" |
#include "ppapi/utility/completion_callback_factory.h" |
// Use assert as a poor-man's CHECK, even in non-debug mode. |
@@ -39,6 +40,19 @@ |
namespace { |
+struct PictureBufferInfo { |
+ PP_PictureBuffer_Dev buffer; |
+ GLenum texture_target; |
+}; |
+ |
+struct Shader { |
+ Shader() : program(0), |
+ texcoord_scale_location(0) {} |
+ |
+ GLuint program; |
+ GLint texcoord_scale_location; |
+}; |
+ |
class VideoDecodeDemoInstance : public pp::Instance, |
public pp::Graphics3DClient, |
public pp::VideoDecoderClient_Dev { |
@@ -90,7 +104,7 @@ class VideoDecodeDemoInstance : public pp::Instance, |
uint32_t texture_target); |
void DismissPictureBuffer(int32_t picture_buffer_id); |
- const PP_PictureBuffer_Dev& GetPictureBufferById(int id); |
+ const PictureBufferInfo& GetPictureBufferInfoById(int id); |
pp::VideoDecoder_Dev* decoder() { return decoder_; } |
private: |
@@ -107,7 +121,7 @@ class VideoDecodeDemoInstance : public pp::Instance, |
size_t encoded_data_next_pos_to_decode_; |
std::set<int> bitstream_ids_at_decoder_; |
// Map of texture buffers indexed by buffer id. |
- typedef std::map<int, PP_PictureBuffer_Dev> PictureBufferMap; |
+ typedef std::map<int, PictureBufferInfo> PictureBufferMap; |
PictureBufferMap picture_buffers_by_id_; |
// Map of bitstream buffers indexed by id. |
typedef std::map<int, pp::Buffer_Dev*> BitstreamBufferMap; |
@@ -119,8 +133,10 @@ class VideoDecodeDemoInstance : public pp::Instance, |
// GL-related functions. |
void InitGL(); |
- GLuint CreateTexture(int32_t width, int32_t height); |
+ GLuint CreateTexture(int32_t width, int32_t height, GLenum texture_target); |
void CreateGLObjects(); |
+ Shader CreateProgram(const char* vertex_shader, |
+ const char* fragment_shader); |
void CreateShader(GLuint program, GLenum type, const char* source, int size); |
void DeleteTexture(GLuint id); |
void PaintFinished(int32_t result, PP_Resource decoder, |
@@ -168,6 +184,11 @@ class VideoDecodeDemoInstance : public pp::Instance, |
pp::Graphics3D* context_; |
typedef std::map<int, DecoderClient*> Decoders; |
Decoders video_decoders_; |
+ |
+ // Shader program to draw GL_TEXTURE_2D target. |
+ Shader shader_2d_; |
+ // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target. |
+ Shader shader_rectangle_arb_; |
}; |
VideoDecodeDemoInstance::DecoderClient::DecoderClient( |
@@ -189,7 +210,7 @@ VideoDecodeDemoInstance::DecoderClient::~DecoderClient() { |
for (PictureBufferMap::iterator it = picture_buffers_by_id_.begin(); |
it != picture_buffers_by_id_.end(); ++it) { |
- gles2_->DeleteTexture(it->second.texture_id); |
+ gles2_->DeleteTexture(it->second.buffer.texture_id); |
} |
picture_buffers_by_id_.clear(); |
} |
@@ -212,6 +233,13 @@ VideoDecodeDemoInstance::VideoDecodeDemoInstance(PP_Instance instance, |
} |
VideoDecodeDemoInstance::~VideoDecodeDemoInstance() { |
+ if (shader_2d_.program) |
+ gles2_if_->DeleteProgram(context_->pp_resource(), shader_2d_.program); |
+ if (shader_rectangle_arb_.program) { |
+ gles2_if_->DeleteProgram( |
+ context_->pp_resource(), shader_rectangle_arb_.program); |
+ } |
+ |
for (Decoders::iterator it = video_decoders_.begin(); |
it != video_decoders_.end(); ++it) { |
delete it->second; |
@@ -337,24 +365,23 @@ void VideoDecodeDemoInstance::DecoderClient::ProvidePictureBuffers( |
uint32_t req_num_of_bufs, |
PP_Size dimensions, |
uint32_t texture_target) { |
- // TODO(sail): Add support for GL_TEXTURE_RECTANGLE_ARB. |
- assert(texture_target == GL_TEXTURE_2D); |
std::vector<PP_PictureBuffer_Dev> buffers; |
for (uint32_t i = 0; i < req_num_of_bufs; ++i) { |
- PP_PictureBuffer_Dev buffer; |
- buffer.size = dimensions; |
- buffer.texture_id = |
- gles2_->CreateTexture(dimensions.width, dimensions.height); |
+ PictureBufferInfo info; |
+ info.buffer.size = dimensions; |
+ info.texture_target = texture_target; |
+ info.buffer.texture_id = gles2_->CreateTexture( |
+ dimensions.width, dimensions.height, info.texture_target); |
int id = ++next_picture_buffer_id_; |
- buffer.id = id; |
- buffers.push_back(buffer); |
- assert(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second); |
+ info.buffer.id = id; |
+ buffers.push_back(info.buffer); |
+ assert(picture_buffers_by_id_.insert(std::make_pair(id, info)).second); |
} |
decoder_->AssignPictureBuffers(buffers); |
} |
-const PP_PictureBuffer_Dev& |
-VideoDecodeDemoInstance::DecoderClient::GetPictureBufferById( |
+const PictureBufferInfo& |
+VideoDecodeDemoInstance::DecoderClient::GetPictureBufferInfoById( |
int id) { |
PictureBufferMap::iterator it = picture_buffers_by_id_.find(id); |
assert(it != picture_buffers_by_id_.end()); |
@@ -370,7 +397,8 @@ void VideoDecodeDemoInstance::DismissPictureBuffer(PP_Resource decoder, |
void VideoDecodeDemoInstance::DecoderClient::DismissPictureBuffer( |
int32_t picture_buffer_id) { |
- gles2_->DeleteTexture(GetPictureBufferById(picture_buffer_id).texture_id); |
+ gles2_->DeleteTexture(GetPictureBufferInfoById( |
+ picture_buffer_id).buffer.texture_id); |
picture_buffers_by_id_.erase(picture_buffer_id); |
} |
@@ -384,8 +412,8 @@ void VideoDecodeDemoInstance::PictureReady(PP_Resource decoder, |
} |
DecoderClient* client = video_decoders_[decoder]; |
assert(client); |
- const PP_PictureBuffer_Dev& buffer = |
- client->GetPictureBufferById(picture.picture_buffer_id); |
+ const PictureBufferInfo& info = |
+ client->GetPictureBufferInfoById(picture.picture_buffer_id); |
assert(!is_painting_); |
is_painting_ = true; |
int x = 0; |
@@ -395,16 +423,33 @@ void VideoDecodeDemoInstance::PictureReady(PP_Resource decoder, |
y = plugin_size_.height() / kNumDecoders; |
} |
+ if (info.texture_target == GL_TEXTURE_2D) { |
+ gles2_if_->UseProgram(context_->pp_resource(), shader_2d_.program); |
+ gles2_if_->Uniform2f( |
+ context_->pp_resource(), shader_2d_.texcoord_scale_location, 1.0, 1.0); |
+ } else { |
+ assert(info.texture_target == GL_TEXTURE_RECTANGLE_ARB); |
+ gles2_if_->UseProgram( |
+ context_->pp_resource(), shader_rectangle_arb_.program); |
+ gles2_if_->Uniform2f(context_->pp_resource(), |
+ shader_rectangle_arb_.texcoord_scale_location, |
+ info.buffer.size.width, |
+ info.buffer.size.height); |
+ } |
+ |
gles2_if_->Viewport(context_->pp_resource(), x, y, |
plugin_size_.width() / kNumDecoders, |
plugin_size_.height() / kNumDecoders); |
gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); |
gles2_if_->BindTexture( |
- context_->pp_resource(), GL_TEXTURE_2D, buffer.texture_id); |
+ context_->pp_resource(), info.texture_target, info.buffer.texture_id); |
gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4); |
+ |
+ gles2_if_->UseProgram(context_->pp_resource(), 0); |
+ |
pp::CompletionCallback cb = |
callback_factory_.NewCallback( |
- &VideoDecodeDemoInstance::PaintFinished, decoder, buffer.id); |
+ &VideoDecodeDemoInstance::PaintFinished, decoder, info.buffer.id); |
last_swap_request_ticks_ = core_if_->GetTimeTicks(); |
assert(context_->SwapBuffers(cb) == PP_OK_COMPLETIONPENDING); |
} |
@@ -483,29 +528,33 @@ void VideoDecodeDemoInstance::PaintFinished(int32_t result, PP_Resource decoder, |
} |
} |
-GLuint VideoDecodeDemoInstance::CreateTexture(int32_t width, int32_t height) { |
+GLuint VideoDecodeDemoInstance::CreateTexture(int32_t width, |
+ int32_t height, |
+ GLenum texture_target) { |
GLuint texture_id; |
gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); |
assertNoGLError(); |
// Assign parameters. |
gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); |
- gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); |
+ gles2_if_->BindTexture(context_->pp_resource(), texture_target, texture_id); |
gles2_if_->TexParameteri( |
- context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
+ context_->pp_resource(), texture_target, GL_TEXTURE_MIN_FILTER, |
GL_NEAREST); |
gles2_if_->TexParameteri( |
- context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
+ context_->pp_resource(), texture_target, GL_TEXTURE_MAG_FILTER, |
GL_NEAREST); |
gles2_if_->TexParameterf( |
- context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, |
+ context_->pp_resource(), texture_target, GL_TEXTURE_WRAP_S, |
GL_CLAMP_TO_EDGE); |
gles2_if_->TexParameterf( |
- context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
+ context_->pp_resource(), texture_target, GL_TEXTURE_WRAP_T, |
GL_CLAMP_TO_EDGE); |
- gles2_if_->TexImage2D( |
- context_->pp_resource(), GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, |
- GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
+ if (texture_target == GL_TEXTURE_2D) { |
+ gles2_if_->TexImage2D( |
+ context_->pp_resource(), texture_target, 0, GL_RGBA, width, height, 0, |
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
+ } |
assertNoGLError(); |
return texture_id; |
} |
@@ -520,13 +569,14 @@ void VideoDecodeDemoInstance::CreateGLObjects() { |
"varying vec2 v_texCoord; \n" |
"attribute vec4 a_position; \n" |
"attribute vec2 a_texCoord; \n" |
+ "uniform vec2 v_scale; \n" |
"void main() \n" |
"{ \n" |
- " v_texCoord = a_texCoord; \n" |
+ " v_texCoord = v_scale * a_texCoord; \n" |
" gl_Position = a_position; \n" |
"}"; |
- static const char kFragmentShader[] = |
+ static const char kFragmentShader2D[] = |
"precision mediump float; \n" |
"varying vec2 v_texCoord; \n" |
"uniform sampler2D s_texture; \n" |
@@ -535,38 +585,63 @@ void VideoDecodeDemoInstance::CreateGLObjects() { |
" gl_FragColor = texture2D(s_texture, v_texCoord); \n" |
"}"; |
- // Create shader program. |
- GLuint program = gles2_if_->CreateProgram(context_->pp_resource()); |
- CreateShader(program, GL_VERTEX_SHADER, kVertexShader, sizeof(kVertexShader)); |
- CreateShader( |
- program, GL_FRAGMENT_SHADER, kFragmentShader, sizeof(kFragmentShader)); |
- gles2_if_->LinkProgram(context_->pp_resource(), program); |
- gles2_if_->UseProgram(context_->pp_resource(), program); |
- gles2_if_->DeleteProgram(context_->pp_resource(), program); |
- gles2_if_->Uniform1i( |
- context_->pp_resource(), |
- gles2_if_->GetUniformLocation( |
- context_->pp_resource(), program, "s_texture"), 0); |
- assertNoGLError(); |
+ static const char kFragmentShaderRectangle[] = |
+ "#extension GL_ARB_texture_rectangle : require\n" |
+ "precision mediump float; \n" |
+ "varying vec2 v_texCoord; \n" |
+ "uniform sampler2DRect s_texture; \n" |
+ "void main() \n" |
+ "{" |
+ " gl_FragColor = texture2DRect(s_texture, v_texCoord).rgba; \n" |
+ "}"; |
// Assign vertex positions and texture coordinates to buffers for use in |
// shader program. |
static const float kVertices[] = { |
-1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. |
- 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. |
+ 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. |
}; |
GLuint buffer; |
gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer); |
gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer); |
+ |
gles2_if_->BufferData(context_->pp_resource(), GL_ARRAY_BUFFER, |
sizeof(kVertices), kVertices, GL_STATIC_DRAW); |
assertNoGLError(); |
+ |
+ shader_2d_ = CreateProgram(kVertexShader, kFragmentShader2D); |
+ shader_rectangle_arb_ = |
+ CreateProgram(kVertexShader, kFragmentShaderRectangle); |
+} |
+ |
+Shader VideoDecodeDemoInstance::CreateProgram(const char* vertex_shader, |
+ const char* fragment_shader) { |
+ Shader shader; |
+ |
+ // Create shader program. |
+ shader.program = gles2_if_->CreateProgram(context_->pp_resource()); |
+ CreateShader(shader.program, GL_VERTEX_SHADER, vertex_shader, |
+ strlen(vertex_shader)); |
+ CreateShader(shader.program, GL_FRAGMENT_SHADER, fragment_shader, |
+ strlen(fragment_shader)); |
+ gles2_if_->LinkProgram(context_->pp_resource(), shader.program); |
+ gles2_if_->UseProgram(context_->pp_resource(), shader.program); |
+ gles2_if_->Uniform1i( |
+ context_->pp_resource(), |
+ gles2_if_->GetUniformLocation( |
+ context_->pp_resource(), shader.program, "s_texture"), 0); |
+ assertNoGLError(); |
+ |
+ shader.texcoord_scale_location = gles2_if_->GetUniformLocation( |
+ context_->pp_resource(), shader.program, "v_scale"); |
+ |
GLint pos_location = gles2_if_->GetAttribLocation( |
- context_->pp_resource(), program, "a_position"); |
+ context_->pp_resource(), shader.program, "a_position"); |
GLint tc_location = gles2_if_->GetAttribLocation( |
- context_->pp_resource(), program, "a_texCoord"); |
+ context_->pp_resource(), shader.program, "a_texCoord"); |
assertNoGLError(); |
+ |
gles2_if_->EnableVertexAttribArray(context_->pp_resource(), pos_location); |
gles2_if_->VertexAttribPointer(context_->pp_resource(), pos_location, 2, |
GL_FLOAT, GL_FALSE, 0, 0); |
@@ -574,7 +649,10 @@ void VideoDecodeDemoInstance::CreateGLObjects() { |
gles2_if_->VertexAttribPointer( |
context_->pp_resource(), tc_location, 2, GL_FLOAT, GL_FALSE, 0, |
static_cast<float*>(0) + 8); // Skip position coordinates. |
+ |
+ gles2_if_->UseProgram(context_->pp_resource(), 0); |
assertNoGLError(); |
+ return shader; |
} |
void VideoDecodeDemoInstance::CreateShader( |