1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : // This file defines hooks for all pepper related srpc calls
8 : // involving images and 2d graphicss.
9 : // This is for experimentation and testing. We are not concerned
10 : // about descriptor and memory leaks
11 :
12 : #include <string.h>
13 : #include <fstream>
14 : #include <queue>
15 : #include <string>
16 :
17 : #if (NACL_LINUX)
18 : // for shmem
19 : #include <sys/ipc.h>
20 : #include <sys/shm.h>
21 : #include "native_client/src/trusted/desc/linux/nacl_desc_sysv_shm.h"
22 : #endif
23 :
24 :
25 : #include "ppapi/c/pp_errors.h"
26 : #include "ppapi/c/pp_input_event.h"
27 : #include "ppapi/c/pp_size.h"
28 : #include "ppapi/c/ppb_image_data.h"
29 :
30 : #include "native_client/src/shared/imc/nacl_imc.h"
31 : #include "native_client/src/shared/platform/nacl_check.h"
32 : #include "native_client/src/shared/srpc/nacl_srpc.h"
33 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
34 :
35 : #include "native_client/src/trusted/sel_universal/primitives.h"
36 : #include "native_client/src/trusted/sel_universal/parsing.h"
37 : #include "native_client/src/trusted/sel_universal/pepper_emu.h"
38 : #include "native_client/src/trusted/sel_universal/pepper_emu_helper.h"
39 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
40 :
41 : #include "native_client/src/trusted/sel_universal/srpc_helper.h"
42 :
43 : using nacl::DescWrapperFactory;
44 : using nacl::DescWrapper;
45 :
46 : // ======================================================================
47 : namespace {
48 :
49 : const int kBytesPerPixel = 4;
50 :
51 : IMultimedia* GlobalMultiMediaInterface = 0;
52 :
53 : struct DataImageData {
54 : int size;
55 : int width;
56 : int height;
57 : nacl::DescWrapper* desc_video_shmem;
58 : void* addr_video;
59 : };
60 :
61 : struct DataGraphics2D {
62 : int image_data;
63 : int width;
64 : int height;
65 : };
66 :
67 : // NOTE: even though this code suggests it can handle multiple
68 : // ImageData and Graphics2D objects it really cannot at this time.
69 22 : Resource<DataGraphics2D> GlobalGraphics2dResources(100, "graphics2d");
70 22 : Resource<DataImageData> GlobalImageDataResources(100, "image_data");
71 :
72 :
73 :
74 : // From the ImageData API
75 : // PP_Resource Create(PP_Instance instance,
76 : // PP_ImageDataFormat format,
77 : // const struct PP_Size* size,
78 : // PP_Bool init_to_zero);
79 : // PPB_ImageData_Create:iiCi:i
80 : //
81 : // TODO(robertm) this function can currently be called only once
82 : // and the dimension must match the global values
83 : // and the format is fixed.
84 0 : static void PPB_ImageData_Create(SRPC_PARAMS) {
85 0 : const int instance = ins[0]->u.ival;
86 0 : const int format = ins[1]->u.ival;
87 0 : CHECK(ins[2]->u.count == sizeof(PP_Size));
88 0 : PP_Size* img_size = (PP_Size*) ins[2]->arrays.carr;
89 : NaClLog(1, "PPB_ImageData_Create(%d, %d, %d, %d)\n",
90 0 : instance, format, img_size->width, img_size->height);
91 :
92 0 : CHECK(format == PP_IMAGEDATAFORMAT_BGRA_PREMUL);
93 0 : CHECK(GlobalMultiMediaInterface->VideoWidth() == img_size->width);
94 0 : CHECK(GlobalMultiMediaInterface->VideoHeight() == img_size->height);
95 :
96 0 : const int handle = GlobalImageDataResources.Alloc();
97 0 : DataImageData* data = GlobalImageDataResources.GetDataForHandle(handle);
98 :
99 0 : data->width = img_size->width;
100 0 : data->height = img_size->height;
101 0 : data->size = kBytesPerPixel * img_size->width * img_size->height;
102 :
103 0 : nacl::DescWrapperFactory factory;
104 0 : data->desc_video_shmem = factory.MakeShm(data->size);
105 : size_t dummy_size;
106 :
107 0 : if (data->desc_video_shmem->Map(&data->addr_video, &dummy_size)) {
108 0 : NaClLog(LOG_FATAL, "cannot map video shmem\n");
109 : }
110 :
111 0 : if (ins[3]->u.ival) {
112 0 : memset(data->addr_video, 0, data->size);
113 : }
114 :
115 0 : outs[0]->u.ival = handle;
116 0 : NaClLog(1, "PPB_ImageData_Create() -> %d\n", handle);
117 0 : rpc->result = NACL_SRPC_RESULT_OK;
118 0 : done->Run(done);
119 0 : }
120 :
121 : // From the ImageData API
122 : // PP_Bool Describe(PP_Resource image_data,
123 : // struct PP_ImageDataDesc* desc);
124 : // PPB_ImageData_Describe:i:Chii
125 0 : static void PPB_ImageData_Describe(SRPC_PARAMS) {
126 0 : int handle = ins[0]->u.ival;
127 0 : NaClLog(1, "PPB_ImageData_Describe(%d)\n", handle);
128 0 : DataImageData* data = GlobalImageDataResources.GetDataForHandle(handle);
129 :
130 : PP_ImageDataDesc d;
131 0 : d.format = PP_IMAGEDATAFORMAT_BGRA_PREMUL;
132 0 : d.size.width = data->width;
133 0 : d.size.height = data->height;
134 : // we handle only rgba data -> each pixel is 4 bytes.
135 0 : d.stride = data->width * kBytesPerPixel;
136 0 : outs[0]->u.count = sizeof(d);
137 0 : outs[0]->arrays.carr = reinterpret_cast<char*>(calloc(1, sizeof(d)));
138 0 : memcpy(outs[0]->arrays.carr, &d, sizeof(d));
139 :
140 0 : outs[1]->u.hval = data->desc_video_shmem->desc();
141 0 : outs[2]->u.ival = data->size;
142 0 : outs[3]->u.ival = 1;
143 0 : rpc->result = NACL_SRPC_RESULT_OK;
144 0 : done->Run(done);
145 0 : }
146 :
147 : // From the Graphics2D API
148 : // PP_Resource Create(PP_Instance instance,
149 : // const struct PP_Size* size,
150 : // PP_Bool is_always_opaque);
151 : // PPB_Graphics2D_Create:iCi:i
152 : //
153 : // TODO(robertm) This function can currently be called only once
154 : // The size must be the same as the one provided via
155 : // HandlerSDLInitialize()
156 0 : static void PPB_Graphics2D_Create(SRPC_PARAMS) {
157 0 : int instance = ins[0]->u.ival;
158 0 : NaClLog(1, "PPB_Graphics2D_Create(%d)\n", instance);
159 0 : const int handle = GlobalGraphics2dResources.Alloc();
160 0 : PP_Size* img_size = reinterpret_cast<PP_Size*>(ins[1]->arrays.carr);
161 : // for enforce fixed dimensions
162 0 : CHECK(GlobalMultiMediaInterface->VideoWidth() == img_size->width);
163 0 : CHECK(GlobalMultiMediaInterface->VideoHeight() == img_size->height);
164 :
165 0 : DataGraphics2D* data = GlobalGraphics2dResources.GetDataForHandle(handle);
166 0 : data->width = img_size->width;
167 0 : data->height = img_size->height;
168 :
169 : // TODO(robertm): is_always_opaque is currently ignored
170 0 : outs[0]->u.ival = handle;
171 0 : NaClLog(1, "PPB_Graphics2D_Create() -> %d\n", handle);
172 0 : rpc->result = NACL_SRPC_RESULT_OK;
173 0 : done->Run(done);
174 0 : }
175 :
176 : // PP_Bool BindGraphics(PP_Instance instance, PP_Resource device);
177 : // PPB_Instance_BindGraphics:ii:i
178 0 : static void PPB_Instance_BindGraphics(SRPC_PARAMS) {
179 0 : int instance = ins[0]->u.ival;
180 0 : int handle = ins[1]->u.ival;
181 0 : NaClLog(1, "PPB_Instance_BindGraphics(%d, %d)\n", instance, handle);
182 : // TODO(robertm):
183 : // Add checking code here for type of handle, e.g. 2d or 3d graphics
184 0 : outs[0]->u.ival = 1;
185 0 : rpc->result = NACL_SRPC_RESULT_OK;
186 0 : done->Run(done);
187 0 : }
188 :
189 : // From the Graphics2D API
190 : // void ReplaceContents(PP_Resource graphics_2d,
191 : // PP_Resource image_data);
192 : // PPB_Graphics2D_ReplaceContents:ii:
193 : //
194 : // NOTE: this is completely ignored and we postpone all action to "Flush"
195 0 : static void PPB_Graphics2D_ReplaceContents(SRPC_PARAMS) {
196 0 : int handle_graphics2d = ins[0]->u.ival;
197 0 : int handle_image_data = ins[1]->u.ival;
198 : UNREFERENCED_PARAMETER(outs);
199 : NaClLog(1, "PPB_Graphics2D_ReplaceContents(%d, %d)\n",
200 0 : handle_graphics2d, handle_image_data);
201 : DataGraphics2D* data_graphics2d =
202 0 : GlobalGraphics2dResources.GetDataForHandle(handle_graphics2d);
203 0 : data_graphics2d->image_data = handle_image_data;
204 :
205 : // For now assume this will be immediately followed by a Flush
206 0 : rpc->result = NACL_SRPC_RESULT_OK;
207 0 : done->Run(done);
208 0 : }
209 :
210 : // From the Graphics2D API
211 : // void PaintImageData(PP_Resource graphics_2d,
212 : // PP_Resource image_data,
213 : // const struct PP_Point* top_left,
214 : // const struct PP_Rect* src_rect);
215 : // PPB_Graphics2D_PaintImageData:iiCC:
216 : //
217 : // NOTE: this is completely ignored and we postpone all action to "Flush"
218 : // Furhermore we assume that entire image is painted
219 0 : static void PPB_Graphics2D_PaintImageData(SRPC_PARAMS) {
220 0 : int handle_graphics2d = ins[0]->u.ival;
221 0 : int handle_image_data = ins[1]->u.ival;
222 : UNREFERENCED_PARAMETER(outs);
223 : NaClLog(1, "PPB_Graphics2D_PaintImageData(%d, %d)\n",
224 0 : handle_graphics2d, handle_image_data);
225 :
226 : DataGraphics2D* data_graphics2d =
227 0 : GlobalGraphics2dResources.GetDataForHandle(handle_graphics2d);
228 0 : data_graphics2d->image_data = handle_image_data;
229 : // For now assume this will be immediately followed by a Flush
230 0 : rpc->result = NACL_SRPC_RESULT_OK;
231 0 : done->Run(done);
232 0 : }
233 :
234 : // From the Graphics2D API
235 : // int32_t Flush(PP_Resource graphics_2d,
236 : // struct PP_CompletionCallback callback);
237 : // PPB_Graphics2D_Flush:ii:i
238 0 : static void PPB_Graphics2D_Flush(SRPC_PARAMS) {
239 0 : int handle = ins[0]->u.ival;
240 0 : int callback_id = ins[1]->u.ival;
241 0 : NaClLog(1, "PPB_Graphics2D_Flush(%d, %d)\n", handle, callback_id);
242 0 : outs[0]->u.ival = -1;
243 0 : rpc->result = NACL_SRPC_RESULT_OK;
244 0 : done->Run(done);
245 :
246 : DataGraphics2D* data_graphics2d =
247 0 : GlobalGraphics2dResources.GetDataForHandle(handle);
248 : DataImageData *image_data =
249 0 : GlobalImageDataResources.GetDataForHandle(data_graphics2d->image_data);
250 0 : GlobalMultiMediaInterface->VideoUpdate(image_data->addr_video);
251 : UserEvent* event =
252 0 : MakeUserEvent(EVENT_TYPE_FLUSH_CALLBACK, callback_id, 0, 0, 0);
253 0 : GlobalMultiMediaInterface->PushUserEvent(event);
254 0 : }
255 :
256 : } // namespace
257 :
258 : #define TUPLE(a, b) #a #b, a
259 0 : void PepperEmuInit2D(NaClCommandLoop* ncl, IMultimedia* im) {
260 0 : GlobalMultiMediaInterface = im;
261 0 : NaClLog(LOG_INFO, "PepperEmuInit2d\n");
262 :
263 0 : ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_Create, :iCi:i));
264 0 : ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_ReplaceContents, :ii:));
265 0 : ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_PaintImageData, :iiCC:));
266 0 : ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_Flush, :ii:i));
267 :
268 0 : ncl->AddUpcallRpc(TUPLE(PPB_ImageData_Describe, :i:Chii));
269 0 : ncl->AddUpcallRpc(TUPLE(PPB_ImageData_Create, :iiCi:i));
270 :
271 0 : ncl->AddUpcallRpc(TUPLE(PPB_Instance_BindGraphics, :ii:i));
272 22 : }
|