1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include "ppapi/c/pp_completion_callback.h" 9 #include "ppapi/c/pp_errors.h" 10 #include "ppapi/c/pp_instance.h" 11 #include "ppapi/c/pp_module.h" 12 #include "ppapi/c/pp_rect.h" 13 #include "ppapi/c/pp_var.h" 14 #include "ppapi/c/ppb.h" 15 #include "ppapi/c/ppb_core.h" 16 #include "ppapi/c/ppb_graphics_2d.h" 17 #include "ppapi/c/ppb_image_data.h" 18 #include "ppapi/c/ppb_instance.h" 19 #include "ppapi/c/ppb_view.h" 20 #include "ppapi/c/ppp.h" 21 #include "ppapi/c/ppp_instance.h" 22 23 PPB_GetInterface g_get_browser_interface = NULL; 24 25 const PPB_Core* g_core_interface; 26 const PPB_Graphics2D* g_graphics_2d_interface; 27 const PPB_ImageData* g_image_data_interface; 28 const PPB_Instance* g_instance_interface; 29 const PPB_View* g_view_interface; 30 31 /* PPP_Instance implementation -----------------------------------------------*/ 32 33 struct InstanceInfo { 34 PP_Instance pp_instance; 35 struct PP_Size last_size; 36 37 struct InstanceInfo* next; 38 }; 39 40 /** Linked list of all live instances. */ 41 struct InstanceInfo* all_instances = NULL; 42 43 /** Returns a refed resource corresponding to the created graphics 2d. */ 44 PP_Resource MakeAndBindGraphics2D(PP_Instance instance, 45 const struct PP_Size* size) { 46 PP_Resource graphics; 47 48 graphics = g_graphics_2d_interface->Create(instance, size, PP_FALSE); 49 if (!graphics) 50 return 0; 51 52 if (!g_instance_interface->BindGraphics(instance, graphics)) { 53 g_core_interface->ReleaseResource(graphics); 54 return 0; 55 } 56 return graphics; 57 } 58 59 void FlushCompletionCallback(void* user_data, int32_t result) { 60 /* Don't need to do anything here. */ 61 } 62 63 void Repaint(struct InstanceInfo* instance, const struct PP_Size* size) { 64 PP_Resource image, graphics; 65 struct PP_ImageDataDesc image_desc; 66 uint32_t* image_data; 67 int num_words, i; 68 69 /* Create image data to paint into. */ 70 image = g_image_data_interface->Create( 71 instance->pp_instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, PP_TRUE); 72 if (!image) 73 return; 74 g_image_data_interface->Describe(image, &image_desc); 75 76 /* Fill the image with blue. */ 77 image_data = (uint32_t*)g_image_data_interface->Map(image); 78 if (!image_data) { 79 g_core_interface->ReleaseResource(image); 80 return; 81 } 82 num_words = image_desc.stride * size->height / 4; 83 for (i = 0; i < num_words; i++) 84 image_data[i] = 0xFF0000FF; 85 86 /* Create the graphics 2d and paint the image to it. */ 87 graphics = MakeAndBindGraphics2D(instance->pp_instance, size); 88 if (!graphics) { 89 g_core_interface->ReleaseResource(image); 90 return; 91 } 92 93 g_graphics_2d_interface->ReplaceContents(graphics, image); 94 g_graphics_2d_interface->Flush(graphics, 95 PP_MakeCompletionCallback(&FlushCompletionCallback, NULL)); 96 97 g_core_interface->ReleaseResource(graphics); 98 g_core_interface->ReleaseResource(image); 99 } 100 101 /** Returns the info for the given instance, or NULL if it's not found. */ 102 struct InstanceInfo* FindInstance(PP_Instance instance) { 103 struct InstanceInfo* cur = all_instances; 104 while (cur) { 105 if (cur->pp_instance == instance) 106 return cur; 107 cur = cur->next; 108 } 109 return NULL; 110 } 111 112 PP_Bool Instance_DidCreate(PP_Instance instance, 113 uint32_t argc, 114 const char* argn[], 115 const char* argv[]) { 116 struct InstanceInfo* info = 117 (struct InstanceInfo*)malloc(sizeof(struct InstanceInfo)); 118 info->pp_instance = instance; 119 info->last_size.width = 0; 120 info->last_size.height = 0; 121 122 /* Insert into linked list of live instances. */ 123 info->next = all_instances; 124 all_instances = info; 125 return PP_TRUE; 126 } 127 128 void Instance_DidDestroy(PP_Instance instance) { 129 /* Find the matching item in the linked list, delete it, and patch the 130 * links. 131 */ 132 struct InstanceInfo** prev_ptr = &all_instances; 133 struct InstanceInfo* cur = all_instances; 134 while (cur) { 135 if (instance == cur->pp_instance) { 136 *prev_ptr = cur->next; 137 free(cur); 138 return; 139 } 140 prev_ptr = &cur->next; 141 cur = cur->next; 142 } 143 } 144 145 void Instance_DidChangeView(PP_Instance pp_instance, 146 PP_Resource view) { 147 struct PP_Rect position; 148 struct InstanceInfo* info = FindInstance(pp_instance); 149 if (!info) 150 return; 151 152 if (g_view_interface->GetRect(view, &position) == PP_FALSE) 153 return; 154 155 if (info->last_size.width != position.size.width || 156 info->last_size.height != position.size.height) { 157 /* Got a resize, repaint the plugin. */ 158 Repaint(info, &position.size); 159 info->last_size.width = position.size.width; 160 info->last_size.height = position.size.height; 161 } 162 } 163 164 void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) { 165 } 166 167 PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance, 168 PP_Resource pp_url_loader) { 169 return PP_FALSE; 170 } 171 172 static PPP_Instance instance_interface = { 173 &Instance_DidCreate, 174 &Instance_DidDestroy, 175 &Instance_DidChangeView, 176 &Instance_DidChangeFocus, 177 &Instance_HandleDocumentLoad 178 }; 179 180 181 /* Global entrypoints --------------------------------------------------------*/ 182 183 PP_EXPORT int32_t PPP_InitializeModule(PP_Module module, 184 PPB_GetInterface get_browser_interface) { 185 g_get_browser_interface = get_browser_interface; 186 187 g_core_interface = (const PPB_Core*) 188 get_browser_interface(PPB_CORE_INTERFACE); 189 g_instance_interface = (const PPB_Instance*) 190 get_browser_interface(PPB_INSTANCE_INTERFACE); 191 g_image_data_interface = (const PPB_ImageData*) 192 get_browser_interface(PPB_IMAGEDATA_INTERFACE); 193 g_graphics_2d_interface = (const PPB_Graphics2D*) 194 get_browser_interface(PPB_GRAPHICS_2D_INTERFACE); 195 g_view_interface = (const PPB_View*) 196 get_browser_interface(PPB_VIEW_INTERFACE); 197 if (!g_core_interface || !g_instance_interface || !g_image_data_interface || 198 !g_graphics_2d_interface || !g_view_interface) 199 return -1; 200 201 return PP_OK; 202 } 203 204 PP_EXPORT void PPP_ShutdownModule() { 205 } 206 207 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { 208 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) 209 return &instance_interface; 210 return NULL; 211 } 212