using the Chromium 3D graphics interface in Ppapi The article describes how to use the Ppb_graphics3d interface, providing a simple example of a single mouse that can transform the color of the plugin.
Foruok original, if you need to reprint please pay attention to Foruok subscription number "program Horizon" contact Foruok.
The Ppb_graphics3d is a 3D graphical interface chromium exposed to PPAPI, similar to the EGL of the Open GL and local windowing systems. We use the Create method of the Ppb_graphics3d to build the context, and then use the Ppb_instance bindgraphics to bind the OpenGL context and the plug-in instance, and then, You can use OpenGL to draw. In the process, Ppb_graphics3d replaced EGL.
Chromium is using WebGL, the OpenGL ES 2.0 for the Web, which exposes the GL interface to PPAPI as a C struct with a function pointer in the form of a ppb_opengles2, ppb_ Opengles2framebufferblit, Ppb_opengles2chromiumenablefeature, and so on, search ppb_opengles2*.h to see the corresponding interface definition.
About OpenGL ES, you can see here: https://www.khronos.org/opengles/.
Using OpenGL ES2 in Ppapi
using the Chromium 3D graphics interface in Ppapi we mentioned Glinitializeppapi and Glsetcurrentcontextppapi two ways to explain this.
The thing Glinitializeppapi do is to get the various GL-related interfaces that the browser exposes to Ppapi (via Ppb_getinterface), which is stored in the global variable (see Gl2ext_ PPAPI.C), subsequent to our use of the glxxx (see GLES2.C) function, is actually implemented by invoking a function pointer through the saved interface (struct + function pointer). The glxxx we use is a macro definition that looks consistent with OpenGL APIs and is easy to use.
I added the following code to the Ppp_initializemodule method in PPAPI_HELLO_GLES.C:
if (GL_TRUE != glInitializePPAPI(get_browser_interface)) return -1;
The above code initializes the PPAPI related GL interface.
The Create method of ppb_graphics3d creates a graphical context, which OpenGL uses to draw. The parameters required for the Glsetcurrentcontextppapi method (see GL2EXT_PPAPI.C) are the context that the Ppb_graphics3d interface created.
The Makeandbindgraphics3d function in PPAPI_HELLO_GLES.C creates the GRAPHICS3D context and calls the GLSETCURRENTCONTEXTPPAPI to pass to the module that encapsulates the GL C interface:
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;}
Well, we've added some additional instructions for using the Chromium 3D graphics interface in Ppapi , and we've learned that you can use the interface of OpenGL ES 2.0 for 3D plotting in Ppapi, which is more than software-and shared-memory graphics The 2D interface is highly efficient, and it leverages GPU acceleration. Next look at how to use the GL interface to draw a simple triangle.
Draw triangles
Modified the Ppapi_hello_gles instance, added the glTriangle.h and gltriangle.c two files, they implemented the triangle drawing. Most of the code I picked up from theOpenGL ES 2.0 ProgrammingGuide was revised for PPAPI.
GlTriangle.h as follows:
#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
Two functions are declared, which are used in PPAPI_HELLO_GLES.C.
Gltriangle.c as follows:
/* Copyright (c) Foruok. All rights reserved.* Welcome to my subscription number program Horizon * 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, cons T char *shadersource) {gluint shader; Glint compiled; Create the Shader object shader = Glcreateshader (type); if (shader = = 0) return 0; Load the shader source Glshadersource (shader, 1, &shadersource, NULL); Compile the shader Glcompileshader (shader); Check the Compile status Glgetshaderiv (shader, Gl_compile_status, &compiled); if (!compiled) {Glint Infolen = 0; Glgetshaderiv (shader, Gl_info_log_length, &infolen); if (Infolen &Gt 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 Shaders Gluint vertexshader = Loadshader (Gl_vertex_shader, VSHADERSTR); Gluint Fragmentshader = Loadshader (Gl_fragment_shader, FSHADERSTR); Create the program object Gluint programobject = Glcreateprogram (); if (Programobject = = 0) return gl_false; Glattachshader (Programobject, vertexshader); Glattachshader (Programobject, Fragmentshader); Blind vposition to attribute 0 glbindattriblocation (programobject, 0, "vposition"); Link the program Gllinkprogram (Programobject); Gldeleteshader (vertexshader); Gldeleteshader (Fragmentshader); Check link status glint 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 Object Gluseprogram (Data->programobject); Load the vertex data glvertexattribpointer (0, 3, gl_float, Gl_false, 0, vvertices); Glenablevertexattribarray (0); Gldrawarrays (gl_triangles, 0, 3);}
GLTRIANGLE.C's three functions are from theOpenGL ES 2.0 ProgrammingGuide, and now the latest book is the OpenGL ES 3.0 Programming Guide. For a detailed explanation of the code, please refer to the book, which is very detailed, organized and super awesome!
Finally, I modified the PPAPI_HELLO_GLES.C to use the Gltriangle interface. The new PPAPI_HELLO_GLES.C content is as follows:
/* Copyright (c) Foruok. All rights reserved.* Welcome to my subscription number program Horizon */#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, +, Pp_graphics3dattrib_height, pp_graphics3dattrib_n One}; 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 does anything here. */if (result = = Pp_error_context_lost) {OutputDebugString (_t ("Pp_error_context_lost")); Reinitialize context G_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 GET A (CLR) (CLR >> &); 0xFF) #define GETR (CLR >>) & 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 read Y. */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 ("Inittriangl E 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[]) {Stru CT 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_DidCh Angeview, &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_interfa Ce->geTposition (input_event); _stprintf_s, Szlog, _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 (i Nterface_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;
The change part I use foruok[1], foruok[2] and the like comments out, a total of 5 places. You can search for a view.
The Inittriangle method is called after calling Makeandbindgraphics3d, creating a shader, program object. The Drawtriangle method is called in repaint, which draws the triangle internally through the gldrawarrays.
Well, the modified example is still simple, but it shows how to use OpenGL ES in Ppapi.
Other reference articles:
- CEF Windows Development Environment Setup
- CEF Load Ppapi Plugin
- VS2013 compiling the simplest Ppapi plugin
- Understanding the design of PPAPI
- Ppapi plugin-to-browser interaction process
- Windows compiled from the source CEF
- Media_stream_video Example of compiling PPAPI
- PPAPI plug-in drawing and input event handling
- Creating a local window in the PPAPI plug-in
- PPAPI plug-in communication with the browser
- Skia compiled from source under Windows
- Using Skia drawing in the Ppapi plug-in
- Load a picture resource in a DLL to generate a Skbitmap object in Skia
- Ppapi+skia implementation of Graffiti Board
- 3D graphics interface using chromium in PPAPI
Using OpenGL ES drawing in Ppapi