Home | History | Annotate | Download | only in 2d
      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