1// Copyright 2013 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_rect.h" 9#include "ppapi/c/pp_resource.h" 10#include "ppapi/c/pp_size.h" 11#include "ppapi/c/ppb_core.h" 12#include "ppapi/c/ppb_graphics_2d.h" 13#include "ppapi/c/ppb_image_data.h" 14#include "ppapi/c/ppb_instance.h" 15#include "ppapi/c/ppb_view.h" 16#include "ppapi/cpp/image_data.h" 17 18#include "ppapi_simple/ps.h" 19#include "ppapi_simple/ps_context_2d.h" 20#include "ppapi_simple/ps_event.h" 21#include "ppapi_simple/ps_instance.h" 22#include "ppapi_simple/ps_interface.h" 23 24PSContext2D_t* PSContext2DAllocate(PP_ImageDataFormat format) { 25 PSContext2D_t* ctx = (PSContext2D_t*) malloc(sizeof(PSContext2D_t)); 26 memset(ctx, 0, sizeof(PSContext2D_t)); 27 28 ctx->format = format; 29 return ctx; 30} 31 32void PSContext2DFree(PSContext2D_t* ctx) { 33 if (ctx->graphic_2d) { 34 PSInterfaceCore()->ReleaseResource(ctx->graphic_2d); 35 ctx->graphic_2d = 0; 36 } 37 if (ctx->image) { 38 PSInterfaceCore()->ReleaseResource(ctx->image); 39 ctx->image = 0; 40 } 41 free(ctx); 42} 43 44PP_ImageDataFormat PSContext2DGetNativeImageDataFormat() { 45 return PSInterfaceImageData()->GetNativeImageDataFormat(); 46} 47 48// Update the 2D context if the message is appropriate, returning non-zero 49// if the event was consumed. 50int PSContext2DHandleEvent(PSContext2D_t* ctx, PSEvent* event) { 51 switch(event->type) { 52 case PSE_INSTANCE_DIDCHANGEVIEW: { 53 struct PP_Rect rect; 54 55 PSInterfaceView()->GetRect(event->as_resource, &rect); 56 PSInterfaceCore()->ReleaseResource(ctx->graphic_2d); 57 ctx->bound = 0; 58 ctx->width = rect.size.width; 59 ctx->height = rect.size.height; 60 61 // Create an opaque graphic context of the specified size. 62 ctx->graphic_2d = 63 PSInterfaceGraphics2D()->Create(PSGetInstanceId(), &rect.size, 64 PP_TRUE); 65 66 // Bind the context to so that draws will be visible. 67 if (ctx->graphic_2d) { 68 ctx->bound = 69 PSInterfaceInstance()->BindGraphics(PSGetInstanceId(), 70 ctx->graphic_2d); 71 } 72 73 // Typically this resource would not be allocated yet, but just in case 74 // throw it away, to force a new allocation when GetBuffer is called. 75 if (ctx->image) { 76 PSInterfaceCore()->ReleaseResource(ctx->image); 77 ctx->image = 0; 78 } 79 80 return 1; 81 } 82 default: break; 83 } 84 85 return 0; 86} 87 88 89// Allocates (if needed) a new image context which will be swapped in when 90// drawing is complete. PSContextGetBuffer and PSContext2DSwapBuffer 91// implemented the suggested image/graphic_2d use specified in the 92// ppb_graphics_2d header. 93int PSContext2DGetBuffer(PSContext2D_t* ctx) { 94 if (!ctx->bound) return 0; 95 96 // Check if we are already holding an image 97 if (ctx->image) return 1; 98 99 PP_Size size; 100 size.width = ctx->width; 101 size.height = ctx->height; 102 103 // Allocate a new image resource with the specified size and format, but 104 // do not ZERO out the buffer first since we will fill it. 105 PP_Resource image = 106 PSInterfaceImageData()->Create(PSGetInstanceId(), ctx->format, &size, 107 PP_FALSE); 108 109 if (0 == image) { 110 PSInstance::GetInstance()->Error("Unable to create 2D image.\n"); 111 return 0; 112 } 113 114 // Get the stride 115 struct PP_ImageDataDesc desc; 116 PSInterfaceImageData()->Describe(image, &desc); 117 118 ctx->image = image; 119 ctx->data = static_cast<uint32_t*>(PSInterfaceImageData()->Map(image)); 120 ctx->stride = desc.stride; 121 return 1; 122} 123 124int PSContext2DSwapBuffer(PSContext2D_t* ctx) { 125 if (ctx->bound && ctx->image) { 126 PSInterfaceImageData()->Unmap(ctx->image); 127 PSInterfaceGraphics2D()->ReplaceContents(ctx->graphic_2d, ctx->image); 128 PSInterfaceGraphics2D()->Flush(ctx->graphic_2d, PP_BlockUntilComplete()); 129 PSInterfaceCore()->ReleaseResource(ctx->image); 130 131 ctx->image = 0; 132 ctx->stride = 0; 133 ctx->data = NULL; 134 return 1; 135 } 136 return 0; 137} 138 139