PPAPI中使用Chromium的3D图形接口一文中我们介绍了怎么使用PPB_Graphics3D接口,提供了一个简单示例,单机鼠标可以变换插件颜色。

foruok原创,如需转载请关注foruok的微信订阅号“程序视界”联系foruok。

PPB_Graphics3D是Chromium暴露给PPAPI的3D图形接口,类似衔接Open GL和本地窗口系统的EGL。我们使用PPB_Graphics3D的Create方法来创建context,然后使用PPB_Instance的BindGraphics将得到的OpenGL Context和插件实例绑定,再接下来,就可以使用OpenGL来绘图了。在这个过程中,PPB_Graphics3D替代了EGL。

Chromium使用的应该是WebGL,也就是OpenGL ES 2.0 for the Web,它暴露给PPAPI的gl接口是C结构体加函数指针的形式,有PPB_OpenGLES2、PPB_OpenGLES2FramebufferBlit、PPB_OpenGLES2ChromiumEnableFeature等,搜索ppb_opengles2*.h即可查看对应的接口定义。

关于OpenGL ES,可以看这里:https://www.khronos.org/opengles/。

PPAPI中使用OpenGL ES2

PPAPI中使用Chromium的3D图形接口一文中我们提到了glInitializePPAPI和glSetCurrentContextPPAPI两个方法,解释一下。

  • glInitializePPAPI

glInitializePPAPI做的事情就是把浏览器暴露给PPAPI的各种gl相关的接口都拿到(通过PPB_GetInterface),保存在全局变量中(参看gl2ext_ppapi.c),后续我们使用glXXX(参看gles2.c)函数时,实际上是通过保存下来的接口(结构体+函数指针),调用函数指针来实现的。我们用到的glXXX是宏定义,看起来和OpenGL的API一致,用起来方便。

我在ppapi_hello_gles.c的PPP_InitializeModule方法中添加了下面的代码:

if (GL_TRUE != glInitializePPAPI(get_browser_interface))return -1;

上面的代码初始化PPAPI相关的gl接口。

  • glSetCurrentContextPPAPI

PPB_Graphics3D的Create方法创建一个图形上下文,OpenGL就用它绘图。glSetCurrentContextPPAPI方法(参看gl2ext_ppapi.c)需要的参数就是PPB_Graphics3D接口Create出来的那个context。

ppapi_hello_gles.c中的MakeAndBindGraphics3D函数创建了Graphics3D context,并调用glSetCurrentContextPPAPI来传递给封装gl C接口的模块:

PP_Resource MakeAndBindGraphics3D(PP_Instance instance,const struct PP_Size* size) {PP_Resource graphics;int32_t attribs[] = { PP_GRAPHICS3DATTRIB_WIDTH, 800,PP_GRAPHICS3DATTRIB_HEIGHT, 800,PP_GRAPHICS3DATTRIB_NONE };graphics = g_graphics_3d_interface->Create(instance, 0, attribs);if (!graphics)return 0;if (!g_instance_interface->BindGraphics(instance, graphics)) {g_core_interface->ReleaseResource(graphics);return 0;}glSetCurrentContextPPAPI(graphics);return graphics;
}

好啦,我们对PPAPI中使用Chromium的3D图形接口一文做了一些补充说明,了解了在PPAPI中可以使用OpenGL ES 2.0的接口来进行3D绘图,这种方式比基于软件和共享内存的Graphics 2D接口效率要高,它利用了GPU加速。接下来看看怎么使用gl接口来绘制一个简单的三角形。

绘制三角形

修改了ppapi_hello_gles实例,添加了glTriangle.h和glTriangle.c两个文件,它们实现了三角形绘制。大部分代码是我从《OpenGL ES 2.0 Programming Guide》一书中摘出来的,针对PPAPI做了修改。

glTriangle.h如下:

#ifndef GLTRIANGLE_DRAW_H
#define GLTRIANGLE_DRAW_H
#include "ppapi/lib/gl/include/GLES2/gl2.h"GLboolean InitTriangle(void **userData);
void DrawTriangle(void *userData);#endif

声明了两个函数,ppapi_hello_gles.c中会用到。

glTriangle.c如下:

/* Copyright (c) 2016 foruok. All rights reserved.
* 欢迎关注我的微信订阅号程序视界
* see: 《OpenGL ES 2.0 Programming Guide》
*/
#include "glTriangle.h"
#include <Windows.h>
#include "ppapi/lib/gl/include/GLES2/gl2.h"
#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
#include "ppapi/lib/gl/include/GLES2/gl2ext.h"
#include <tchar.h>typedef struct
{GLuint programObject;
} UserData;/** create a shader object, load the shader source, and compile the shader*/
GLuint LoadShader(GLenum type, const char *shaderSource)
{GLuint shader;GLint compiled;// create the shader objectshader = glCreateShader(type);if (shader == 0)return 0;// load the shader sourceglShaderSource(shader, 1, &shaderSource, NULL);// compile the shaderglCompileShader(shader);// check the compile statusglGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);if (!compiled){GLint infoLen = 0;glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1){char *infoLog = malloc(infoLen+1);glGetShaderInfoLog(shader, infoLen, NULL, infoLog);infoLog[infoLen] = 0;OutputDebugStringA(infoLog);free(infoLog);}glDeleteShader(shader);return 0;}return shader;
}/** Initialize the shader and program object*/
GLboolean InitTriangle(void **userData)
{GLbyte vShaderStr[] ="attribute vec4 vPosition; \n""void main() \n""{ \n""    gl_Position = vPosition; \n""} \n";GLbyte fShaderStr[] ="precision mediump float; \n""void main() \n""{ \n""    gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); \n""} \n";// load shadersGLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);// create the program objectGLuint programObject = glCreateProgram();if (programObject == 0) return GL_FALSE;glAttachShader(programObject, vertexShader);glAttachShader(programObject, fragmentShader);// blind vPosition to attribute 0glBindAttribLocation(programObject, 0, "vPosition");// link the programglLinkProgram(programObject);glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// check link statusGLint linked;glGetProgramiv(programObject, GL_LINK_STATUS, &linked);if (!linked){GLint infoLen = 0;glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1){char *infoLog = malloc(infoLen + 1);glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);infoLog[infoLen] = 0;OutputDebugStringA(infoLog);free(infoLog);}glDeleteProgram(programObject);return GL_FALSE;}UserData *data = *userData;if (data == 0){data = (UserData*)malloc(sizeof(UserData));*userData = data;}data->programObject = programObject;return GL_TRUE;
}void DrawTriangle(void *userData)
{OutputDebugString(_T("DrawTriagle\r\n"));UserData *data = userData;GLfloat vVertices[] = {0.0f, 0.5f, 0.0f,-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f};// use the program objectglUseProgram(data->programObject);// load the vertex dataglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);glEnableVertexAttribArray(0);glDrawArrays(GL_TRIANGLES, 0, 3);
}

glTriangle.c的三个函数都来自《OpenGL ES 2.0 Programming Guide》一书,现在最新的书应该是《OpenGL ES 3.0 Programming Guide》。详细的代码解说请参考该书,非常详尽、有条理,超级棒!

最后,我修改了ppapi_hello_gles.c,以便使用glTriangle的接口。新的ppapi_hello_gles.c内容如下:

/* Copyright (c) 2016 foruok. All rights reserved.
* 欢迎关注我的微信订阅号程序视界
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <tchar.h>#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_view.h"
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppb_input_event.h"
#include "ppapi/c/ppp_input_event.h"
#include "ppapi/c/ppb_graphics_3d.h"
#include "ppapi/c/ppb_opengles2.h"
#include "ppapi/lib/gl/include/GLES2/gl2.h"
#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
// foruok[1]
#include "glTriangle.h"PPB_GetInterface g_get_browser_interface = NULL;const PPB_Core* g_core_interface;
const PPB_Graphics3D* g_graphics_3d_interface;
const PPB_Instance* g_instance_interface;
const PPB_View* g_view_interface;
const PPB_InputEvent *g_input_interface;
const PPB_MouseInputEvent *g_mouse_interface;/* PPP_Instance implementation -----------------------------------------------*/typedef struct InstanceInfo {PP_Instance pp_instance;struct PP_Size last_size;PP_Resource graphics;// foruok[2]void *user_data;struct InstanceInfo* next;
} InstanceInfo;/** Linked list of all live instances. */
struct InstanceInfo* all_instances = NULL;/** Returns a refed resource corresponding to the created graphics 3d. */
PP_Resource MakeAndBindGraphics3D(PP_Instance instance,const struct PP_Size* size) {PP_Resource graphics;int32_t attribs[] = { PP_GRAPHICS3DATTRIB_WIDTH, 800,PP_GRAPHICS3DATTRIB_HEIGHT, 800,PP_GRAPHICS3DATTRIB_NONE };graphics = g_graphics_3d_interface->Create(instance, 0, attribs);if (!graphics)return 0;if (!g_instance_interface->BindGraphics(instance, graphics)) {g_core_interface->ReleaseResource(graphics);return 0;}glSetCurrentContextPPAPI(graphics);return graphics;
}void ReinitializeGraphics3D(void *user_data, int32_t result)
{InstanceInfo *inst = (InstanceInfo*)user_data;inst->graphics = MakeAndBindGraphics3D(inst->pp_instance, &inst->last_size);if (inst->graphics != 0){// foruok[5]if(inst->user_data)InitTriangle(inst->user_data);OutputDebugString(_T("reinitialize graphics 3d context sucess\r\n"));}
}void FlushCompletionCallback(void* user_data, int32_t result) {/* Don't need to do anything here. */if (result == PP_ERROR_CONTEXT_LOST){OutputDebugString(_T("PP_ERROR_CONTEXT_LOST"));//reinitialize contextg_core_interface->CallOnMainThread(0, PP_MakeCompletionCallback(ReinitializeGraphics3D, user_data), 0);}
}unsigned int g_colors[4] = { 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFF2AFE00 };
unsigned int g_color_index = 0;
#define GETA(clr) ((clr >> 24) & 0xFF)
#define GETR(clr) ((clr >> 16) & 0xFF)
#define GETG(clr) ((clr >> 8) & 0xFF)
#define GETB(clr) (clr & 0xFF)void Repaint(struct InstanceInfo* instance, const struct PP_Size* size) {/* Ensure the graphics 3d is ready. */if (!instance->graphics) {instance->graphics = MakeAndBindGraphics3D(instance->pp_instance, size);if (!instance->graphics)return;// foruok[3]if (GL_TRUE == InitTriangle(&instance->user_data))OutputDebugString(_T("InitTriangle OK\r\n"));}g_color_index++;if (g_color_index >= sizeof(g_colors) / sizeof(g_colors[0])) g_color_index = 0;struct PP_CompletionCallback callback = {FlushCompletionCallback, instance, PP_COMPLETIONCALLBACK_FLAG_NONE,};glViewport(0, 0, instance->last_size.width, instance->last_size.height);glClearColor(GETR(g_colors[g_color_index]),GETG(g_colors[g_color_index]),GETB(g_colors[g_color_index]),GETA(g_colors[g_color_index]));glClear(GL_COLOR_BUFFER_BIT);// foruok[4]if(instance->user_data)DrawTriangle(instance->user_data);g_graphics_3d_interface->SwapBuffers(instance->graphics, callback);
}/** Returns the info for the given instance, or NULL if it's not found. */
struct InstanceInfo* FindInstance(PP_Instance instance) {struct InstanceInfo* cur = all_instances;while (cur) {if (cur->pp_instance == instance)return cur;cur = cur->next;}return NULL;
}PP_Bool Instance_DidCreate(PP_Instance instance,uint32_t argc,const char* argn[],const char* argv[]) {struct InstanceInfo* info =(struct InstanceInfo*)calloc(1, sizeof(struct InstanceInfo));info->pp_instance = instance;/* Insert into linked list of live instances. */info->next = all_instances;all_instances = info;g_input_interface->RequestInputEvents(instance, PP_INPUTEVENT_CLASS_MOUSE);g_input_interface->RequestFilteringInputEvents(instance, PP_INPUTEVENT_CLASS_MOUSE);OutputDebugString(_T("Instance_DidCreate\r\n"));return PP_TRUE;
}void Instance_DidDestroy(PP_Instance instance) {/* Find the matching item in the linked list, delete it, and patch the* links.*/struct InstanceInfo** prev_ptr = &all_instances;struct InstanceInfo* cur = all_instances;while (cur) {if (instance == cur->pp_instance) {*prev_ptr = cur->next;g_core_interface->ReleaseResource(cur->graphics);free(cur);return;}prev_ptr = &cur->next;cur = cur->next;}
}void Instance_DidChangeView(PP_Instance pp_instance,PP_Resource view) {struct PP_Rect position;struct InstanceInfo* info = FindInstance(pp_instance);if (!info)return;if (g_view_interface->GetRect(view, &position) == PP_FALSE)return;if (info->last_size.width != position.size.width ||info->last_size.height != position.size.height) {info->last_size.width = position.size.width;info->last_size.height = position.size.height;/* Got a resize, repaint the plugin. */Repaint(info, &position.size);}OutputDebugString(_T("Instance_DidChangeView\r\n"));
}void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
}PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,PP_Resource pp_url_loader) {return PP_FALSE;
}static PPP_Instance instance_interface = {&Instance_DidCreate,&Instance_DidDestroy,&Instance_DidChangeView,&Instance_DidChangeFocus,&Instance_HandleDocumentLoad
};PP_Bool InputEvent_HandleInputEvent(PP_Instance instance, PP_Resource input_event)
{struct PP_Point pt;TCHAR szLog[512] = { 0 };switch (g_input_interface->GetType(input_event)){case PP_INPUTEVENT_TYPE_MOUSEDOWN:pt = g_mouse_interface->GetPosition(input_event);_stprintf_s(szLog, 512, _T("InputEvent_HandleInputEvent, mouse down at [%d, %d]\r\n"), pt.x, pt.y);OutputDebugString(szLog);break;default:return PP_FALSE;}struct InstanceInfo* info = FindInstance(instance);if (info && info->last_size.width > 0){Repaint(info, &info->last_size);}return PP_TRUE;
}static PPP_InputEvent input_interface = {&InputEvent_HandleInputEvent
};/* Global entrypoints --------------------------------------------------------*/PP_EXPORT int32_t PPP_InitializeModule(PP_Module module,PPB_GetInterface get_browser_interface) {g_get_browser_interface = get_browser_interface;g_core_interface = (const PPB_Core*)get_browser_interface(PPB_CORE_INTERFACE);g_instance_interface = (const PPB_Instance*)get_browser_interface(PPB_INSTANCE_INTERFACE);g_graphics_3d_interface = (const PPB_Graphics3D*)get_browser_interface(PPB_GRAPHICS_3D_INTERFACE);g_view_interface = (const PPB_View*)get_browser_interface(PPB_VIEW_INTERFACE);g_input_interface = (const PPB_InputEvent*)get_browser_interface(PPB_INPUT_EVENT_INTERFACE);g_mouse_interface = (const PPB_MouseInputEvent*)get_browser_interface(PPB_MOUSE_INPUT_EVENT_INTERFACE);if (!g_core_interface || !g_instance_interface ||!g_graphics_3d_interface || !g_view_interface ||!g_input_interface || !g_mouse_interface)return -1;if (GL_TRUE != glInitializePPAPI(get_browser_interface))return -1;OutputDebugString(_T("PPP_InitializeModule\r\n"));return PP_OK;
}PP_EXPORT void PPP_ShutdownModule() {
}PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0){OutputDebugString(_T("PPP_GetInterface, instance_interface\r\n"));return &instance_interface;}else if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0){OutputDebugString(_T("PPP_GetInterface, input_interface\r\n"));return &input_interface;}return NULL;
}

改动部分我用foruok[1]、foruok[2]之类的注释标注出来了,共有5处。可以搜索查看。

InitTriangle方法在调用MakeAndBindGraphics3D之后调用,创建了shader、program object。DrawTriangle方法是在Repaint中被调用的,它内部通过glDrawArrays来绘制三角形。


好啦,这个改造过的示例依然很简单,不过可以演示如何在PPAPI中使用OpenGL ES。

其他参考文章:

  • CEF Windows开发环境搭建
  • CEF加载PPAPI插件
  • VS2013编译最简单的PPAPI插件
  • 理解PPAPI的设计
  • PPAPI插件与浏览器的交互过程
  • Windows下从源码编译CEF
  • 编译PPAPI的media_stream_video示例
  • PPAPI插件的绘图与输入事件处理
  • 在PPAPI插件中创建本地窗口
  • PPAPI插件与浏览器的通信
  • Windows下从源码编译Skia
  • 在PPAPI插件中使用Skia绘图
  • 加载DLL中的图片资源生成Skia中的SkBitmap对象
  • PPAPI+Skia实现的涂鸦板
  • PPAPI中使用Chromium的3D图形接口

PPAPI中使用OpenGL ES绘图相关推荐

  1. 在Android中使用OpenGL ES开发第(五)节:GLSL基础语法

    一.前期基础储备 笔者之前的四篇文综述了Android中使用OpenGL ES绘制基本图形和实现了简单的相机预览,初次接触OpenGL ES开发的读者可能对其中新的概念比较迷惑,尤其是其中的顶点着色器 ...

  2. Qt中使用OpenGL进行绘图

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  3. 在 iOS 中使用 OpenGL ES 实现绘画板

    作者:lyman 来源: http://www.lymanli.com/2020/01/04/ios-opengles-paint/ 今天我们使用 OpenGL ES 来实现一个绘画板,主要介绍在 O ...

  4. android opengl版本太低,如何提高android中的opengl es显示性能

    我正在努力提高Android视频会议项目的视频显示效率.视频显示以本机opengl代码实现. opengl代码以opengl版本1的原生实现.下面给出的代码用于显示视频的每个帧. int ofi_vc ...

  5. 使用Android OpenGL ES 2.0绘图之一:搭建一个OpenGL ES环境

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 传送门☞系统架构设计☞转载请注明☞http://blog.csdn.net/levera ...

  6. OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow

    1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...

  7. Android下Opengl ES实现单屏幕双眼显示

    http://blog.csdn.net/u011371324/article/details/68946779 默认情况下,Opengl ES使用系统提供的帧缓冲区作为绘图表面,一般情况下,如果只在 ...

  8. 安卓学习笔记37:利用OpenGL ES绘制平面图形

    文章目录 零.学习目标 一.OpenGL概述 二.了解三维直角坐标系 三.案例演示 - 绘制三角形 (一)运行效果 (二)实现步骤 1.创建安卓应用[DrawTriangle] 2.建模:创建三角形类 ...

  9. OpenGl文章 Android OpenGL ES 简明开发教程

    Android OpenGL ES 简明开发教程 分类:android学习笔记2011-12-14 15:04375人阅读评论(0)收藏举报 ApiDemos 的Graphics示例中含有OpenGL ...

  10. OpenGL ES与EGL的关系(二十一)

    什么是OpenGL? Open Graphics Library (OpenGL) is a cross-language, cross-platform application programmin ...

最新文章

  1. PNAS:微生物组分析揭示人类皮肤的独特性
  2. LINUX的20练习题
  3. 【研究】大脑如何在“知道”与“无知”之间做出决定
  4. 2018-12-04-Python全栈开发-day92-自动登录
  5. 笔记-项目立项管理-项目建议书
  6. 人工机器:jetbot小车密码
  7. 程序员面试金典 - 面试题 08.13. 堆箱子(DP)
  8. git配置全局用户名和密码_还在手动打包,手动传jar包?那你确实应该学一下jekins配置了...
  9. php中使用websocket
  10. Mysql触发器与动态完整性
  11. java 100个定时任务_Java定时任务解决方案
  12. 2.微服务:从设计到部署 --- 使用 API 网关
  13. 极限学习机和支持向量机_极限学习机的发展
  14. 用python海龟画一个三角形_海龟画笔---和孩子一起学python
  15. html 模拟鼠标移动,如何在网页端用js模拟鼠标移动点击等操作
  16. linux英文转换成中文
  17. 2.1 VB语言基础——关键字和标识符
  18. 第2篇:Python 基础语法
  19. GNS3中配置直连交换端口的路由器端口IP地址
  20. 手机端点击<li>标签出现背景色的问题和解决方案

热门文章

  1. 电大计算机绘图三锥图形,电大机械制图课程教学辅导
  2. MPPT算法(恒定电压、扰动观察、电导增量)介绍与实现过程
  3. 【笔记整理】电磁场复习——麦克斯韦四个方程组
  4. Origin曲线拟合教程
  5. c语言tc2.0编译器下载,c语言tc2.0下载
  6. python添加环境变量代码_Maya中的PYTHONPATH 环境变量
  7. centos 安装rarlinux
  8. python cnn 实例_Python实现CNN的多通道输入实例
  9. 计算机病毒相关参考文献,计算机病毒参考文献
  10. CnPack20090801更新包