Commit 2c0936a2 authored by yuweih's avatar yuweih Committed by Commit bot

[Remoting] OpenGL Rendering Layer

This CL implements the OpenGL canvas, rendering layer, and desktop. This is part
of the project of implementing OpenGL rendering component for Android and iOS.
Please see design doc in crbug for more information.

BUG=385924

Review-Url: https://codereview.chromium.org/2045963004
Cr-Commit-Position: refs/heads/master@{#405278}
parent e842df6a
......@@ -26,6 +26,7 @@ shared_library("remoting_client_jni") {
"//remoting/android:jni_headers",
"//remoting/base",
"//remoting/client",
"//remoting/client:opengl_renderer",
"//remoting/protocol",
"//ui/events:dom_keycode_converter",
"//ui/gfx",
......
......@@ -41,6 +41,27 @@ source_set("client") {
}
}
if (is_android || is_ios) {
source_set("opengl_renderer") {
sources = [
"gl_canvas.cc",
"gl_canvas.h",
"gl_desktop.cc",
"gl_desktop.h",
"gl_helpers.cc",
"gl_helpers.h",
"gl_render_layer.cc",
"gl_render_layer.h",
]
deps = [
"//third_party/webrtc",
]
configs += [ "//third_party/khronos:khronos_headers" ]
}
}
source_set("test_support") {
testonly = true
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/client/gl_canvas.h"
#include "base/logging.h"
#include "remoting/client/gl_helpers.h"
namespace {
const int kVertexSize = 2;
const int kVertexCount = 4;
const char kTexCoordToViewVert[] =
// Region of the texture to be used (normally the whole texture).
"varying vec2 v_texCoord;\n"
"attribute vec2 a_texCoord;\n"
// Positions to draw the texture on the texture coordinates.
"attribute vec2 a_position;\n"
"uniform mat3 u_transform;\n"
// This matrix translates normalized texture coordinates
// ([0, 1] starting at upper-left corner) to the view coordinates
// ([-1, 1] starting at the center of the screen).
// Note that the matrix is defined in column-major order.
"const mat3 tex_to_view = mat3(2, 0, 0,\n"
" 0, -2, 0,\n"
" -1, 1, 0);\n"
"void main() {\n"
" v_texCoord = a_texCoord;\n"
// Transforms coordinates related to the canvas to coordinates
// related to the view.
" vec3 trans_position = u_transform * vec3(a_position, 1.0);\n"
// Transforms texture coordinates to view coordinates and adds
// projection component 1.
" gl_Position = vec4(tex_to_view * trans_position, 1.0);\n"
"}";
const char kDrawTexFrag[] =
"precision mediump float;\n"
// Region on the texture to be used (normally the whole texture).
"varying vec2 v_texCoord;\n"
"uniform sampler2D u_texture;\n"
"void main() {\n"
" gl_FragColor = texture2D(u_texture, v_texCoord);\n"
"}";
} // namespace
namespace remoting {
GlCanvas::GlCanvas(int gl_version) : gl_version_(gl_version) {
vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kTexCoordToViewVert);
fragment_shader_ = CompileShader(GL_FRAGMENT_SHADER, kDrawTexFrag);
program_ = CreateProgram(vertex_shader_, fragment_shader_);
glUseProgram(program_);
transform_location_ = glGetUniformLocation(program_, "u_transform");
texture_location_ = glGetUniformLocation(program_, "u_texture");
position_location_ = glGetAttribLocation(program_, "a_position");
tex_cord_location_ = glGetAttribLocation(program_, "a_texCoord");
glEnableVertexAttribArray(position_location_);
glEnableVertexAttribArray(tex_cord_location_);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
GlCanvas::~GlCanvas() {
DCHECK(thread_checker_.CalledOnValidThread());
glDisable(GL_BLEND);
glDisableVertexAttribArray(tex_cord_location_);
glDisableVertexAttribArray(position_location_);
glDeleteProgram(program_);
glDeleteShader(vertex_shader_);
glDeleteShader(fragment_shader_);
}
void GlCanvas::SetNormalizedTransformation(const std::array<float, 9>& matrix) {
DCHECK(thread_checker_.CalledOnValidThread());
glUniformMatrix3fv(transform_location_, 1, GL_TRUE, matrix.data());
transformation_set_ = true;
}
void GlCanvas::DrawTexture(int texture_id,
GLuint texture_handle,
GLuint vertex_buffer) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!transformation_set_) {
return;
}
glActiveTexture(GL_TEXTURE0 + texture_id);
glBindTexture(GL_TEXTURE_2D, texture_handle);
glUniform1i(texture_location_, texture_id);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(position_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0,
0);
glVertexAttribPointer(tex_cord_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0,
static_cast<float*>(0) + kVertexSize * kVertexCount);
glDrawArrays(GL_TRIANGLE_STRIP, 0, kVertexCount);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
int GlCanvas::GetGlVersion() const {
return gl_version_;
}
} // namespace remoting
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_CLIENT_OPENGL_GL_CANVAS_H_
#define REMOTING_CLIENT_OPENGL_GL_CANVAS_H_
#include <array>
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "remoting/client/sys_opengl.h"
namespace remoting {
// This class holds zoom and pan configurations of the canvas and is used to
// draw textures on the canvas.
// Must be constructed after the OpenGL surface is created and destroyed before
// the surface is destroyed.
//
// Coordinates to be used for GlCanvas should be normalized texture coordinates.
// In the view of a point on the canvas, the canvas has width 1 and height 1,
// with the origin at the upper-left corner of the canvas.
class GlCanvas {
public:
// gl_version: version number of the OpenGL ES context. Either 2 or 3.
GlCanvas(int gl_version);
~GlCanvas();
// Sets the normalized transformation matrix. This matrix defines how the
// canvas should be shown on the view.
// 3 by 3 transformation matrix, [ m0, m1, m2, m3, m4, m5, m6, m7, m8 ].
// The matrix will be multiplied with the positions (with projective space,
// (x, y, 1)) to draw the textures with the right zoom and pan configuration.
//
// | m0, m1, m2, | | x |
// | m3, m4, m5, | * | y |
// | m6, m7, m8 | | 1 |
//
// For a typical transformation matrix such that m1=m3=m6=m7=0 and m8=1, m0
// and m4 defines the ratio of canvas width or height over view width or
// height. m2 and m5 defines the offset of the upper-left corner in percentage
// of the view's width or height. An identity matrix will stretch the canvas
// to fit the whole view.
void SetNormalizedTransformation(const std::array<float, 9>& matrix);
// Draws the texture on the canvas. Nothing will happen if
// SetNormalizedTransformation() has not been called.
// vertex_buffer: reference to the 2x4x2 float vertex buffer.
// [ four (x, y) normalized vertex positions on the canvas,
// four (x, y) vertex positions to define the visible area ]
void DrawTexture(int texture_id, GLuint texture_handle, GLuint vertex_buffer);
// Returns the version number of current OpenGL ES context. Either 2 or 3.
int GetGlVersion() const;
private:
int gl_version_;
// True IFF the transformation has been set.
bool transformation_set_ = false;
// Handles.
GLuint vertex_shader_;
GLuint fragment_shader_;
GLuint program_;
// Locations of the corresponding shader attributes.
GLuint transform_location_;
GLuint texture_location_;
GLuint position_location_;
GLuint tex_cord_location_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(GlCanvas);
};
} // namespace remoting
#endif // REMOTING_CLIENT_OPENGL_GL_CANVAS_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/client/gl_desktop.h"
#include "base/logging.h"
#include "remoting/client/gl_canvas.h"
#include "remoting/client/gl_render_layer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
namespace {
const int kTextureId = 0;
} // namespace
namespace remoting {
GlDesktop::GlDesktop() {}
GlDesktop::~GlDesktop() {}
void GlDesktop::SetCanvas(GlCanvas* canvas) {
if (!canvas) {
layer_.reset();
return;
}
layer_.reset(new GlRenderLayer(kTextureId, canvas));
if (last_frame_) {
layer_->SetTexture(last_frame_->data(), last_frame_->size().width(),
last_frame_->size().height());
}
}
void GlDesktop::SetVideoFrame(std::unique_ptr<webrtc::DesktopFrame> frame) {
if (layer_) {
if (!last_frame_ || !frame->size().equals(last_frame_->size())) {
layer_->SetTexture(frame->data(), frame->size().width(),
frame->size().height());
} else {
for (webrtc::DesktopRegion::Iterator i(frame->updated_region());
!i.IsAtEnd(); i.Advance()) {
const uint8_t* rect_start =
frame->GetFrameDataAtPos(i.rect().top_left());
layer_->UpdateTexture(
rect_start, i.rect().left(), i.rect().top(), i.rect().width(),
i.rect().height(), frame->stride());
}
}
}
last_frame_ = std::move(frame);
}
void GlDesktop::Draw() {
if (layer_ && last_frame_) {
layer_->Draw();
}
}
} // namespace remoting
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_CLIENT_OPENGL_GL_DESKTOP_H_
#define REMOTING_CLIENT_OPENGL_GL_DESKTOP_H_
#include <memory>
#include "base/macros.h"
namespace webrtc {
class DesktopFrame;
class DesktopRegion;
} // namespace webrtc
namespace remoting {
class GlCanvas;
class GlRenderLayer;
// This class draws the desktop on the canvas.
class GlDesktop {
public:
GlDesktop();
virtual ~GlDesktop();
void SetVideoFrame(std::unique_ptr<webrtc::DesktopFrame> frame);
// Sets the canvas on which the desktop will be drawn. Resumes the current
// state of the desktop to the context of the new canvas.
// If |canvas| is nullptr, nothing will happen when calling Draw().
void SetCanvas(GlCanvas* canvas);
// Draws the desktop on the canvas.
void Draw();
private:
std::unique_ptr<GlRenderLayer> layer_;
std::unique_ptr<webrtc::DesktopFrame> last_frame_;
DISALLOW_COPY_AND_ASSIGN(GlDesktop);
};
} // namespace remoting
#endif // REMOTING_CLIENT_OPENGL_GL_DESKTOP_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/client/gl_helpers.h"
#include "base/logging.h"
namespace remoting {
GLuint CompileShader(GLenum shader_type, const char* shader_source) {
GLuint shader = glCreateShader(shader_type);
if (shader != 0) {
int shader_source_length = strlen(shader_source);
// Pass in the shader source.
glShaderSource(shader, 1, &shader_source, &shader_source_length);
// Compile the shader.
glCompileShader(shader);
// Get the compilation status.
GLint compile_status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
// If the compilation failed, delete the shader.
if (compile_status == GL_FALSE) {
LOG(ERROR) << "Error compiling shader: \n" << shader_source;
glDeleteShader(shader);
shader = 0;
}
}
if (shader == 0) {
LOG(FATAL) << "Error creating shader.";
}
return shader;
}
GLuint CreateProgram(GLuint vertex_shader, GLuint fragment_shader) {
GLuint program = glCreateProgram();
if (program != 0) {
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// Get the link status.
GLint link_status;
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
// If the link failed, delete the program.
if (link_status == GL_FALSE) {
LOG(ERROR) << "Error compiling program.";
glDeleteProgram(program);
program = 0;
}
}
if (program == 0) {
LOG(FATAL) << "Error creating program.";
}
return program;
}
GLuint CreateTexture() {
GLuint texture;
glGenTextures(1, &texture);
if (texture == 0) {
LOG(FATAL) << "Error creating texture.";
}
return texture;
}
GLuint CreateBuffer(const void* data, int size) {
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return buffer;
}
} // namespace remoting
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_CLIENT_GL_HELPERS_H_
#define REMOTING_CLIENT_GL_HELPERS_H_
#include "base/macros.h"
#include "remoting/client/sys_opengl.h"
namespace remoting {
// Compiles a shader and returns the reference to the shader if it succeeds.
GLuint CompileShader(GLenum shader_type, const char* shader_source);
// Creates a program with the given reference to the vertex shader and fragment
// shader. returns the reference of the program if it succeeds.
GLuint CreateProgram(GLuint vertex_shader, GLuint fragment_shader);
// Creates and returns the texture names if it succeeds.
GLuint CreateTexture();
// Creates a GL_ARRAY_BUFFER and fills it with |data|. Returns the reference to
// the buffer.
GLuint CreateBuffer(const void* data, int size);
} // namespace remoting
#endif // REMOTING_CLIENT_GL_HELPERS_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/client/gl_render_layer.h"
#include "base/logging.h"
#include "remoting/client/gl_canvas.h"
#include "remoting/client/gl_helpers.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
namespace {
// Assign texture coordinates to buffers for use in shader program.
const float kVertices[] = {
// Points order: upper-left, bottom-left, upper-right, bottom-right.
// Positions to draw the texture on the normalized canvas coordinate.
0, 0, 0, 1, 1, 0, 1, 1,
// Region of the texture to be used (normally the whole texture).
0, 0, 0, 1, 1, 0, 1, 1};
const int kDefaultUpdateBufferCapacity =
2048 * 2048 * webrtc::DesktopFrame::kBytesPerPixel;
}
namespace remoting {
GlRenderLayer::GlRenderLayer(int texture_id, GlCanvas* canvas)
: texture_id_(texture_id), canvas_(canvas) {
texture_handle_ = CreateTexture();
buffer_handle_ = CreateBuffer(kVertices, sizeof(kVertices));
}
GlRenderLayer::~GlRenderLayer() {
DCHECK(thread_checker_.CalledOnValidThread());
glDeleteBuffers(1, &buffer_handle_);
glDeleteTextures(1, &texture_handle_);
}
void GlRenderLayer::SetTexture(const uint8_t* texture, int width, int height) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK(width > 0 && height > 0);
texture_set_ = true;
glActiveTexture(GL_TEXTURE0 + texture_id_);
glBindTexture(GL_TEXTURE_2D, texture_handle_);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
void PackDirtyRegion(uint8_t* dest,
const uint8_t* source,
int width,
int height,
int stride) {
for (int i = 0; i < height; i++) {
memcpy(dest, source, width * webrtc::DesktopFrame::kBytesPerPixel);
source += stride;
dest += webrtc::DesktopFrame::kBytesPerPixel * width;
}
}
void GlRenderLayer::UpdateTexture(const uint8_t* subtexture,
int offset_x,
int offset_y,
int width,
int height,
int stride) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(texture_set_);
DCHECK(width > 0 && height > 0);
glActiveTexture(GL_TEXTURE0 + texture_id_);
glBindTexture(GL_TEXTURE_2D, texture_handle_);
bool stride_multiple_of_bytes_per_pixel =
stride % webrtc::DesktopFrame::kBytesPerPixel == 0;
bool loosely_packed =
!stride_multiple_of_bytes_per_pixel ||
(stride > 0 && stride != webrtc::DesktopFrame::kBytesPerPixel * width);
const void* buffer_to_update = subtexture;
if (loosely_packed) {
if (stride_multiple_of_bytes_per_pixel && canvas_->GetGlVersion() >= 3) {
glPixelStorei(GL_UNPACK_ROW_LENGTH,
stride / webrtc::DesktopFrame::kBytesPerPixel);
} else {
// Doesn't support GL_UNPACK_ROW_LENGTH or stride not multiple of
// kBytesPerPixel. Manually pack the data.
int required_size = width * height * webrtc::DesktopFrame::kBytesPerPixel;
if (update_buffer_size_ < required_size) {
if (required_size < kDefaultUpdateBufferCapacity) {
update_buffer_size_ = kDefaultUpdateBufferCapacity;
} else {
update_buffer_size_ = required_size;
}
update_buffer_.reset(new uint8_t[update_buffer_size_]);
}
PackDirtyRegion(update_buffer_.get(), subtexture, width, height, stride);
buffer_to_update = update_buffer_.get();
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, offset_x, offset_y, width, height, GL_RGBA,
GL_UNSIGNED_BYTE, buffer_to_update);
if (loosely_packed && stride_multiple_of_bytes_per_pixel &&
canvas_->GetGlVersion() >= 3) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
glBindTexture(GL_TEXTURE_2D, 0);
}
void GlRenderLayer::SetVertexPositions(const std::array<float, 8>& positions) {
DCHECK(thread_checker_.CalledOnValidThread());
glBindBuffer(GL_ARRAY_BUFFER, buffer_handle_);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(kVertices) / 2, positions.data());
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GlRenderLayer::SetTextureVisibleArea(
const std::array<float, 8>& positions) {
DCHECK(thread_checker_.CalledOnValidThread());
glBindBuffer(GL_ARRAY_BUFFER, buffer_handle_);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(kVertices) / 2, sizeof(kVertices) / 2,
positions.data());
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GlRenderLayer::Draw() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(texture_set_);
canvas_->DrawTexture(texture_id_, texture_handle_, buffer_handle_);
}
} // namespace remoting
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_CLIENT_OPENGL_GL_RENDER_LAYER_H_
#define REMOTING_CLIENT_OPENGL_GL_RENDER_LAYER_H_
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "remoting/client/sys_opengl.h"
namespace remoting {
class GlCanvas;
// This class is for drawing a texture on the canvas. Must be deleted before the
// canvas is deleted.
class GlRenderLayer {
public:
// texture_id: An integer in range [0, GL_MAX_TEXTURE_IMAGE_UNITS], defining
// which slot to store the texture.
GlRenderLayer(int texture_id, GlCanvas* canvas);
~GlRenderLayer();
// Sets the texture (RGBA 8888) to be drawn. Please use UpdateTexture() if the
// texture size isn't changed.
void SetTexture(const uint8_t* texture, int width, int height);
// Updates a subregion (RGBA 8888) of the texture.
// stride: byte distance between two rows in |subtexture|.
// If |stride| is 0 or |stride| == |width|*kBytesPerPixel, |subtexture| will
// be treated as tightly packed.
void UpdateTexture(const uint8_t* subtexture,
int offset_x,
int offset_y,
int width,
int height,
int stride);
// Sets the positions of four vertices of the texture in normalized
// coordinates. The default values are (0, 0), (0, 1), (1, 0), (1, 1),
// i.e. stretching the texture to fit the whole canvas.
// positions: [ x_upperleft, y_upperleft, x_lowerleft, y_lowerleft,
// x_upperright, y_upperright, x_lowerright, y_lowerright ]
void SetVertexPositions(const std::array<float, 8>& positions);
// Sets the visible area of the texture. The default values are (0, 0),
// (0, 1), (1, 0), (1, 1), i.e. showing the whole texture.
// positions: [ x_upperleft, y_upperleft, x_lowerleft, y_lowerleft,
// x_upperright, y_upperright, x_lowerright, y_lowerright ]
void SetTextureVisibleArea(const std::array<float, 8>& positions);
// Draws the texture on the canvas. Texture must be set before calling Draw().
void Draw();
private:
int texture_id_;
GlCanvas* canvas_;
GLuint texture_handle_;
GLuint buffer_handle_;
// true IFF the texture is already set by calling SetTexture().
bool texture_set_ = false;
// Used in OpenGL ES 2 context which doesn't support GL_UNPACK_ROW_LENGTH to
// tightly pack dirty regions before sending them to GPU.
std::unique_ptr<uint8_t[]> update_buffer_;
int update_buffer_size_ = 0;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(GlRenderLayer);
};
} // namespace remoting
#endif // REMOTING_CLIENT_OPENGL_GL_RENDER_LAYER_H_
......@@ -8,7 +8,7 @@
#import "remoting/client/ios/example_view_controller.h"
#import "remoting/client/opengl_wrapper.h"
#import "remoting/client/sys_opengl.h"
@interface ExampleViewController()
......
shaders = [
"tex_coord_to_view.vert",
"draw_tex.frag",
]
action("inline_shaders") {
script = "../../tools/build/shader_to_header.py"
out_path = "${root_gen_dir}/remoting/client/opengl/shaders.h"
inputs = shaders
outputs = [
out_path,
]
args = [ rebase_path(out_path) ] + rebase_path(shaders)
}
......@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_CLIENT_OPENGL_WRAPPER_H_
#define REMOTING_CLIENT_OPENGL_WRAPPER_H_
#ifndef REMOTING_CLIENT_SYS_OPENGL_H_
#define REMOTING_CLIENT_SYS_OPENGL_H_
#include "build/build_config.h"
#if defined(OS_IOS)
#include <OpenGLES/ES2/gl.h>
#endif // defined(OS_IOS)
#include <OpenGLES/ES3/gl.h>
#elif defined(OS_ANDROID)
#include <GLES3/gl3.h>
#else
#error OpenGL renderer not supported on this platform.
#endif
#endif // REMOTING_CLIENT_OPENGL_WRAPPER_H_
#endif // REMOTING_CLIENT_SYS_OPENGL_H_
......@@ -186,4 +186,22 @@
'includes': [ 'remoting_webapp.gypi', ],
}, # end of target 'remoting_webapp'
], # end of targets
'conditions': [
['OS=="ios" or OS=="android"', {
'targets': [
{
'target_name': 'remoting_opengl_renderer',
'type': '<(component)',
'sources': [
'<@(remoting_opengl_renderer_sources)',
],
'dependencies': [
'../third_party/khronos/khronos.gyp:khronos_headers',
'../third_party/webrtc/webrtc.gyp:webrtc'
]
} # end of target 'remoting_opengl_renderer'
]
}] # end of conditions 'OS=="ios" or OS=="android"'
]
}
......@@ -349,5 +349,16 @@
'client/plugin/pepper_video_renderer_3d.cc',
'client/plugin/pepper_video_renderer_3d.h',
],
'remoting_opengl_renderer_sources': [
'client/gl_canvas.cc',
'client/gl_canvas.h',
'client/gl_desktop.cc',
'client/gl_desktop.h',
'client/gl_helpers.cc',
'client/gl_helpers.h',
'client/gl_render_layer.cc',
'client/gl_render_layer.h'
],
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment