| /* Copyright (c) 2012 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 <stdint.h> | |
| #include <stdlib.h> | |
| #include <string.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_graphics_2d.h" | |
| #include "ppapi/c/ppb_image_data.h" | |
| #include "ppapi/c/ppb_instance.h" | |
| #include "ppapi/c/ppb_view.h" | |
| #include "ppapi/c/ppp.h" | |
| #include "ppapi/c/ppp_instance.h" | |
| PPB_GetInterface g_get_browser_interface = NULL; | |
| const PPB_Core* g_core_interface; | |
| const PPB_Graphics2D* g_graphics_2d_interface; | |
| const PPB_ImageData* g_image_data_interface; | |
| const PPB_Instance* g_instance_interface; | |
| const PPB_View* g_view_interface; | |
| /* PPP_Instance implementation -----------------------------------------------*/ | |
| struct InstanceInfo { | |
| PP_Instance pp_instance; | |
| struct PP_Size last_size; | |
| PP_Resource graphics; | |
| struct InstanceInfo* next; | |
| }; | |
| /** Linked list of all live instances. */ | |
| struct InstanceInfo* all_instances = NULL; | |
| /** Returns a refed resource corresponding to the created graphics 2d. */ | |
| PP_Resource MakeAndBindGraphics2D(PP_Instance instance, | |
| const struct PP_Size* size) { | |
| PP_Resource graphics; | |
| graphics = g_graphics_2d_interface->Create(instance, size, PP_FALSE); | |
| if (!graphics) | |
| return 0; | |
| if (!g_instance_interface->BindGraphics(instance, graphics)) { | |
| g_core_interface->ReleaseResource(graphics); | |
| return 0; | |
| } | |
| return graphics; | |
| } | |
| void FlushCompletionCallback(void* user_data, int32_t result) { | |
| /* Don't need to do anything here. */ | |
| } | |
| void Repaint(struct InstanceInfo* instance, const struct PP_Size* size) { | |
| PP_Resource image; | |
| struct PP_ImageDataDesc image_desc; | |
| uint32_t* image_data; | |
| int num_words, i; | |
| /* Ensure the graphics 2d is ready. */ | |
| if (!instance->graphics) { | |
| instance->graphics = MakeAndBindGraphics2D(instance->pp_instance, size); | |
| if (!instance->graphics) | |
| return; | |
| } | |
| /* Create image data to paint into. */ | |
| image = g_image_data_interface->Create( | |
| instance->pp_instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, PP_TRUE); | |
| if (!image) | |
| return; | |
| g_image_data_interface->Describe(image, &image_desc); | |
| /* Fill the image with blue. */ | |
| image_data = (uint32_t*)g_image_data_interface->Map(image); | |
| if (!image_data) { | |
| g_core_interface->ReleaseResource(image); | |
| return; | |
| } | |
| num_words = image_desc.stride * size->height / 4; | |
| for (i = 0; i < num_words; i++) | |
| image_data[i] = 0xFF0000FF; | |
| /* Paint image to graphics 2d. */ | |
| g_graphics_2d_interface->ReplaceContents(instance->graphics, image); | |
| g_graphics_2d_interface->Flush(instance->graphics, | |
| PP_MakeCompletionCallback(&FlushCompletionCallback, NULL)); | |
| g_core_interface->ReleaseResource(image); | |
| } | |
| /** 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*)malloc(sizeof(struct InstanceInfo)); | |
| info->pp_instance = instance; | |
| info->last_size.width = 0; | |
| info->last_size.height = 0; | |
| info->graphics = 0; | |
| /* Insert into linked list of live instances. */ | |
| info->next = all_instances; | |
| all_instances = info; | |
| 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) { | |
| /* Got a resize, repaint the plugin. */ | |
| Repaint(info, &position.size); | |
| info->last_size.width = position.size.width; | |
| info->last_size.height = position.size.height; | |
| } | |
| } | |
| 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 | |
| }; | |
| /* 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_image_data_interface = (const PPB_ImageData*) | |
| get_browser_interface(PPB_IMAGEDATA_INTERFACE); | |
| g_graphics_2d_interface = (const PPB_Graphics2D*) | |
| get_browser_interface(PPB_GRAPHICS_2D_INTERFACE); | |
| g_view_interface = (const PPB_View*) | |
| get_browser_interface(PPB_VIEW_INTERFACE); | |
| if (!g_core_interface || !g_instance_interface || !g_image_data_interface || | |
| !g_graphics_2d_interface || !g_view_interface) | |
| return -1; | |
| 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) | |
| return &instance_interface; | |
| return NULL; | |
| } |