1/* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * Copyright (c) Imagination Technologies Limited, UK 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26/* 27 * Authors: 28 * Li Zeng <li.zeng@intel.com> 29 */ 30#include "tng_vld_dec.h" 31#include "psb_drv_debug.h" 32#include "hwdefs/dxva_fw_ctrl.h" 33#include "hwdefs/reg_io2.h" 34#include "hwdefs/msvdx_offsets.h" 35#include "hwdefs/msvdx_cmds_io2.h" 36#include "va/va_dec_jpeg.h" 37#include "va/va_dec_vp8.h" 38 39#define GET_SURFACE_INFO_colocated_index(psb_surface) ((int) (psb_surface->extra_info[3])) 40#define SET_SURFACE_INFO_colocated_index(psb_surface, val) psb_surface->extra_info[3] = (uint32_t) val; 41 42/* Set MSVDX Front end register */ 43void vld_dec_FE_state(object_context_p obj_context, psb_buffer_p buf) 44{ 45 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 46 context_DEC_p ctx = (context_DEC_p) obj_context->format_data; 47 CTRL_ALLOC_HEADER *cmd_header = (CTRL_ALLOC_HEADER *)psb_cmdbuf_alloc_space(cmdbuf, sizeof(CTRL_ALLOC_HEADER)); 48 49 cmd_header->ui32Cmd_AdditionalParams = CMD_CTRL_ALLOC_HEADER; 50 cmd_header->ui32ExternStateBuffAddr = 0; 51 if (buf) 52 RELOC(cmd_header->ui32ExternStateBuffAddr, 0, buf); 53 cmd_header->ui32MacroblockParamAddr = 0; /* Only EC needs to set this */ 54 55 ctx->cmd_params = &cmd_header->ui32Cmd_AdditionalParams; 56 ctx->p_slice_params = &cmd_header->ui32SliceParams; 57 cmd_header->ui32SliceParams = 0; 58 59 ctx->slice_first_pic_last = &cmd_header->uiSliceFirstMbYX_uiPicLastMbYX; 60 *ctx->slice_first_pic_last = 0; 61 62 ctx->p_range_mapping_base0 = &cmd_header->ui32AltOutputAddr[0]; 63 ctx->p_range_mapping_base1 = &cmd_header->ui32AltOutputAddr[1]; 64 65 ctx->alt_output_flags = &cmd_header->ui32AltOutputFlags; 66 67 cmd_header->ui32AltOutputFlags = 0; 68 cmd_header->ui32AltOutputAddr[0] = 0; 69 cmd_header->ui32AltOutputAddr[1] = 0; 70} 71 72/* Programme the Alt output if there is a rotation*/ 73void vld_dec_setup_alternative_frame(object_context_p obj_context) 74{ 75 uint32_t cmd = 0; 76 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 77 context_DEC_p ctx = (context_DEC_p) obj_context->format_data; 78 psb_surface_p src_surface = obj_context->current_render_target->psb_surface; 79 psb_surface_p out_loop_surface = obj_context->current_render_target->out_loop_surface; 80 int ved_scaling = (CONTEXT_SCALING(obj_context) && !ctx->yuv_ctx); 81 uint32_t startX = 0, startY = 0, luma_addr_offset = 0, chroma_addr_offset = 0; 82 83 /* In VPP ctx, current_render_target is rotated surface */ 84 if (ctx->yuv_ctx && (VAEntrypointVideoProc == obj_context->entry_point)) { 85 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Setup second-pass rotation\n"); 86 out_loop_surface = src_surface; 87 src_surface = ctx->yuv_ctx->src_surface; 88 } 89 90 if (CONTEXT_ALTERNATIVE_OUTPUT(obj_context) || obj_context->entry_point == VAEntrypointVideoProc) { 91 if (ved_scaling) { 92 out_loop_surface = obj_context->current_render_target->scaling_surface; 93#ifndef BAYTRAIL 94 tng_ved_write_scale_reg(obj_context); 95 96 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION, SCALE_INPUT_SIZE_SEL, 1); 97 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION, SCALE_ENABLE, 1); 98#endif 99 } else { 100 startX = ((uint32_t)obj_context->current_render_target->offset_x_s + 0x3f) & ~0x3f; 101 startY = ((uint32_t)obj_context->current_render_target->offset_y_s + 0x1) & ~0x1; 102 luma_addr_offset = (((uint32_t)(startX + out_loop_surface->stride * startY)) + 0x3f ) & ~0x3f; 103 chroma_addr_offset = (((uint32_t)(startX + out_loop_surface->stride * startY / 2)) + 0x3f ) & ~0x3f; 104 } 105 106 if (out_loop_surface == NULL) { 107 drv_debug_msg(VIDEO_DEBUG_ERROR, "out-loop surface is NULL, abort msvdx alternative output\n"); 108 return; 109 } 110 111 if (GET_SURFACE_INFO_rotate(out_loop_surface) != obj_context->msvdx_rotate && !ved_scaling) 112 drv_debug_msg(VIDEO_DEBUG_WARNING, "Display rotate mode does not match surface rotate mode!\n"); 113 114 /* CRendecBlock RendecBlk( mCtrlAlloc , RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); */ 115 psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS)); 116 117 psb_cmdbuf_rendec_write_address(cmdbuf, &out_loop_surface->buf, out_loop_surface->buf.buffer_ofs + luma_addr_offset); 118 psb_cmdbuf_rendec_write_address(cmdbuf, &out_loop_surface->buf, out_loop_surface->buf.buffer_ofs + chroma_addr_offset + out_loop_surface->chroma_offset); 119 120 psb_cmdbuf_rendec_end(cmdbuf); 121 122 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ALT_PICTURE_ENABLE, 1); 123 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_ROW_STRIDE, out_loop_surface->stride_mode); 124 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */ 125 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_MODE, GET_SURFACE_INFO_rotate(out_loop_surface)); 126 127 RELOC(*ctx->p_range_mapping_base0, out_loop_surface->buf.buffer_ofs + luma_addr_offset, &out_loop_surface->buf); 128 RELOC(*ctx->p_range_mapping_base1, out_loop_surface->buf.buffer_ofs + chroma_addr_offset + out_loop_surface->chroma_offset, &out_loop_surface->buf); 129 } 130 131 if (obj_context->profile == VAProfileVP8Version0_3 || 132 obj_context->profile == VAProfileJPEGBaseline || ctx->yuv_ctx) { 133 psb_cmdbuf_rendec_start(cmdbuf, (REG_MSVDX_CMD_OFFSET + MSVDX_CMDS_AUX_LINE_BUFFER_BASE_ADDRESS_OFFSET)); 134 psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->aux_line_buffer_vld, ctx->aux_line_buffer_vld.buffer_ofs); 135 psb_cmdbuf_rendec_end(cmdbuf); 136 137 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, USE_AUX_LINE_BUF, 1); 138 if (ctx->yuv_ctx) 139 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 1); 140 } 141 142 /* Set the rotation registers */ 143 psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION)); 144 psb_cmdbuf_rendec_write(cmdbuf, cmd); 145 *ctx->alt_output_flags = cmd; 146 147 cmd = 0; 148 REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, src_surface->stride / 64); 149 psb_cmdbuf_rendec_write(cmdbuf, cmd); 150 151 psb_cmdbuf_rendec_end(cmdbuf); 152} 153 154int vld_dec_slice_parameter_size(object_context_p obj_context) 155{ 156 int size; 157 158 switch (obj_context->profile) { 159 case VAProfileMPEG2Simple: 160 case VAProfileMPEG2Main: 161 size = sizeof(VASliceParameterBufferMPEG2); 162 break; 163 case VAProfileMPEG4Simple: 164 case VAProfileMPEG4AdvancedSimple: 165 case VAProfileMPEG4Main: 166 case VAProfileH263Baseline: 167 size = sizeof(VASliceParameterBufferMPEG4); 168 break; 169 case VAProfileH264Baseline: 170 case VAProfileH264Main: 171 case VAProfileH264High: 172 case VAProfileH264ConstrainedBaseline: 173 size = sizeof(VASliceParameterBufferH264); 174 break; 175 case VAProfileVC1Simple: 176 case VAProfileVC1Main: 177 case VAProfileVC1Advanced: 178 size = sizeof(VASliceParameterBufferVC1); 179 break; 180 case VAProfileVP8Version0_3: 181 size = sizeof(VASliceParameterBufferVP8); 182 case VAProfileJPEGBaseline: 183 size = sizeof(VASliceParameterBufferJPEGBaseline); 184 default: 185 size = 0; 186 break; 187 } 188 189 return size; 190} 191 192VAStatus vld_dec_process_slice_data(context_DEC_p ctx, object_buffer_p obj_buffer) 193{ 194 VAStatus vaStatus = VA_STATUS_SUCCESS; 195 void *slice_param; 196 int buffer_idx = 0; 197 unsigned int element_idx = 0, element_size; 198 199 ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType)); 200 201 ASSERT(ctx->pic_params); 202 ASSERT(ctx->slice_param_list_idx); 203 204#if 0 205 if (!ctx->pic_params) { 206 /* Picture params missing */ 207 return VA_STATUS_ERROR_UNKNOWN; 208 } 209#endif 210 if ((NULL == obj_buffer->psb_buffer) || 211 (0 == obj_buffer->size)) { 212 /* We need to have data in the bitstream buffer */ 213 return VA_STATUS_ERROR_UNKNOWN; 214 } 215 216 element_size = vld_dec_slice_parameter_size(ctx->obj_context); 217 218 while (buffer_idx < ctx->slice_param_list_idx) { 219 object_buffer_p slice_buf = ctx->slice_param_list[buffer_idx]; 220 if (element_idx >= slice_buf->num_elements) { 221 /* Move to next buffer */ 222 element_idx = 0; 223 buffer_idx++; 224 continue; 225 } 226 227 slice_param = slice_buf->buffer_data; 228 slice_param = (void *)((unsigned long)slice_param + element_idx * element_size); 229 element_idx++; 230 vaStatus = vld_dec_process_slice(ctx, slice_param, obj_buffer); 231 if (vaStatus != VA_STATUS_SUCCESS) { 232 DEBUG_FAILURE; 233 break; 234 } 235 } 236 ctx->slice_param_list_idx = 0; 237 238 return vaStatus; 239} 240/* 241 * Adds a VASliceParameterBuffer to the list of slice params 242 */ 243VAStatus vld_dec_add_slice_param(context_DEC_p ctx, object_buffer_p obj_buffer) 244{ 245 ASSERT(obj_buffer->type == VASliceParameterBufferType); 246 if (ctx->slice_param_list_idx >= ctx->slice_param_list_size) { 247 unsigned char *new_list; 248 ctx->slice_param_list_size += 8; 249 new_list = realloc(ctx->slice_param_list, 250 sizeof(object_buffer_p) * ctx->slice_param_list_size); 251 if (NULL == new_list) { 252 return VA_STATUS_ERROR_ALLOCATION_FAILED; 253 } 254 ctx->slice_param_list = (object_buffer_p*) new_list; 255 } 256 ctx->slice_param_list[ctx->slice_param_list_idx] = obj_buffer; 257 ctx->slice_param_list_idx++; 258 return VA_STATUS_SUCCESS; 259} 260 261void vld_dec_write_kick(object_context_p obj_context) 262{ 263 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 264 *cmdbuf->cmd_idx++ = CMD_COMPLETION; 265} 266 267VAStatus vld_dec_process_slice(context_DEC_p ctx, 268 void *vld_slice_param, 269 object_buffer_p obj_buffer) 270{ 271 VAStatus vaStatus = VA_STATUS_SUCCESS; 272 VASliceParameterBufferBase *slice_param = (VASliceParameterBufferBase *) vld_slice_param; 273 274 ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType)); 275 276 if ((slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_BEGIN) || 277 (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL)) { 278#ifndef SLICE_HEADER_PARSING 279 if (0 == slice_param->slice_data_size) { 280 vaStatus = VA_STATUS_ERROR_UNKNOWN; 281 DEBUG_FAILURE; 282 return vaStatus; 283 } 284#endif 285 ASSERT(!ctx->split_buffer_pending); 286 287 if (psb_context_get_next_cmdbuf(ctx->obj_context)) { 288 vaStatus = VA_STATUS_ERROR_UNKNOWN; 289 DEBUG_FAILURE; 290 return vaStatus; 291 } 292 vld_dec_FE_state(ctx->obj_context, ctx->preload_buffer); 293 ctx->begin_slice(ctx, slice_param); 294 ctx->slice_data_buffer = obj_buffer->psb_buffer; 295#ifdef SLICE_HEADER_PARSING 296 if (ctx->parse_enabled == 1) 297 psb_cmdbuf_dma_write_key(ctx->obj_context->cmdbuf, 298 ctx->SR_flags, 299 ctx->parse_key); 300 else 301#endif 302 psb_cmdbuf_dma_write_bitstream(ctx->obj_context->cmdbuf, 303 obj_buffer->psb_buffer, 304 obj_buffer->psb_buffer->buffer_ofs + slice_param->slice_data_offset, 305 slice_param->slice_data_size, 306 ctx->bits_offset, 307 ctx->SR_flags); 308 309 if (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_BEGIN) { 310 ctx->split_buffer_pending = TRUE; 311 } 312 } else { 313 ASSERT(ctx->split_buffer_pending); 314 ASSERT(0 == slice_param->slice_data_offset); 315 if (slice_param->slice_data_size) { 316 psb_cmdbuf_dma_write_bitstream_chained(ctx->obj_context->cmdbuf, 317 obj_buffer->psb_buffer, 318 slice_param->slice_data_size); 319 } 320 } 321 322 if ((slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL) || 323 (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_END)) { 324 if (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_END) { 325 ASSERT(ctx->split_buffer_pending); 326 } 327 328 ctx->process_slice(ctx, slice_param); 329 vld_dec_write_kick(ctx->obj_context); 330 331 ctx->split_buffer_pending = FALSE; 332 ctx->obj_context->video_op = psb_video_vld; 333 ctx->obj_context->flags = 0; 334 335 ctx->end_slice(ctx); 336 337 if (psb_context_submit_cmdbuf(ctx->obj_context)) { 338 vaStatus = VA_STATUS_ERROR_UNKNOWN; 339 } 340 } 341 return vaStatus; 342} 343 344VAStatus vld_dec_allocate_colocated_buffer(context_DEC_p ctx, object_surface_p obj_surface, uint32_t size) 345{ 346 psb_buffer_p buf; 347 VAStatus vaStatus; 348 psb_surface_p surface = obj_surface->psb_surface; 349 int index = GET_SURFACE_INFO_colocated_index(surface); 350 351 if (!index) { 352 index = ctx->colocated_buffers_idx; 353 if (index >= ctx->colocated_buffers_size) { 354 return VA_STATUS_ERROR_UNKNOWN; 355 } 356 357 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocating colocated buffer for surface %08x size = %08x\n", surface, size); 358 359 buf = &(ctx->colocated_buffers[index]); 360 vaStatus = psb_buffer_create(ctx->obj_context->driver_data, size, psb_bt_vpu_only, buf); 361 if (VA_STATUS_SUCCESS != vaStatus) { 362 return vaStatus; 363 } 364 ctx->colocated_buffers_idx++; 365 SET_SURFACE_INFO_colocated_index(surface, index + 1); /* 0 means unset, index is offset by 1 */ 366 } else { 367 buf = &(ctx->colocated_buffers[index - 1]); 368 if (buf->size < size) { 369 psb_buffer_destroy(buf); 370 vaStatus = psb_buffer_create(ctx->obj_context->driver_data, size, psb_bt_vpu_only, buf); 371 if (VA_STATUS_SUCCESS != vaStatus) { 372 return vaStatus; 373 } 374 SET_SURFACE_INFO_colocated_index(surface, index); /* replace the original buffer */ 375 } 376 } 377 return VA_STATUS_SUCCESS; 378} 379 380psb_buffer_p vld_dec_lookup_colocated_buffer(context_DEC_p ctx, psb_surface_p surface) 381{ 382 int index = GET_SURFACE_INFO_colocated_index(surface); 383 if (!index) { 384 return NULL; 385 } 386 return &(ctx->colocated_buffers[index-1]); /* 0 means unset, index is offset by 1 */ 387} 388 389VAStatus vld_dec_CreateContext(context_DEC_p ctx, object_context_p obj_context) 390{ 391 VAStatus vaStatus = VA_STATUS_SUCCESS; 392 393 ctx->obj_context = obj_context; 394 ctx->split_buffer_pending = FALSE; 395 ctx->slice_param_list_size = 8; 396 ctx->slice_param_list = (object_buffer_p*) calloc(1, sizeof(object_buffer_p) * ctx->slice_param_list_size); 397 ctx->slice_param_list_idx = 0; 398 399 if (NULL == ctx->slice_param_list) { 400 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 401 DEBUG_FAILURE; 402 return vaStatus; 403 } 404 405 ctx->colocated_buffers_size = obj_context->num_render_targets; 406 ctx->colocated_buffers_idx = 0; 407 ctx->colocated_buffers = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s) * ctx->colocated_buffers_size); 408 if (NULL == ctx->colocated_buffers) { 409 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 410 DEBUG_FAILURE; 411 free(ctx->slice_param_list); 412 } 413 414 if (vaStatus == VA_STATUS_SUCCESS) { 415 vaStatus = psb_buffer_create(obj_context->driver_data, 416 AUX_LINE_BUFFER_VLD_SIZE, 417 psb_bt_cpu_vpu, 418 &ctx->aux_line_buffer_vld); 419 DEBUG_FAILURE; 420 } 421 422 return vaStatus; 423} 424 425void vld_dec_DestroyContext(context_DEC_p ctx) 426{ 427 int i; 428 ctx->preload_buffer = NULL; 429 430 psb_buffer_destroy(&ctx->aux_line_buffer_vld); 431 432 if (ctx->slice_param_list) { 433 free(ctx->slice_param_list); 434 ctx->slice_param_list = NULL; 435 } 436 437 if (ctx->colocated_buffers) { 438 for (i = 0; i < ctx->colocated_buffers_idx; ++i) 439 psb_buffer_destroy(&(ctx->colocated_buffers[i])); 440 441 free(ctx->colocated_buffers); 442 ctx->colocated_buffers = NULL; 443 } 444} 445 446VAStatus vld_dec_RenderPicture( 447 object_context_p obj_context, 448 object_buffer_p *buffers, 449 int num_buffers) 450{ 451 int i; 452 context_DEC_p ctx = (context_DEC_p) obj_context->format_data; 453 VAStatus vaStatus = VA_STATUS_SUCCESS; 454 455 for (i = 0; i < num_buffers; i++) { 456 object_buffer_p obj_buffer = buffers[i]; 457 psb__dump_va_buffers_verbose(obj_buffer); 458 459 switch (obj_buffer->type) { 460 case VASliceParameterBufferType: 461 vaStatus = vld_dec_add_slice_param(ctx, obj_buffer); 462 DEBUG_FAILURE; 463 break; 464 465 case VASliceDataBufferType: 466 case VAProtectedSliceDataBufferType: 467 vaStatus = vld_dec_process_slice_data(ctx, obj_buffer); 468 DEBUG_FAILURE; 469 break; 470 471 default: 472 vaStatus = ctx->process_buffer(ctx, obj_buffer); 473 DEBUG_FAILURE; 474 } 475 if (vaStatus != VA_STATUS_SUCCESS) { 476 break; 477 } 478 } 479 480 return vaStatus; 481} 482 483void vld_dec_yuv_rotate(object_context_p obj_context) 484{ 485 VAStatus vaStatus = VA_STATUS_SUCCESS; 486 struct format_vtable_s *vtable = &tng_yuv_processor_vtable; 487 struct surface_param_s surface_param; 488 struct object_buffer_s buffer; 489 object_buffer_p buffer_p = &buffer; 490 491 surface_param.src_surface = obj_context->current_render_target->scaling_surface; 492 surface_param.display_width = obj_context->current_render_target->buffer_width_s; 493 surface_param.display_height = obj_context->current_render_target->buffer_height_s; 494 surface_param.coded_width = obj_context->current_render_target->width_s; 495 surface_param.coded_height = obj_context->current_render_target->height_s; 496 497 buffer.num_elements = 1; 498 buffer.type = YUVProcessorSurfaceType; 499 buffer.size = sizeof(struct surface_param_s); 500 buffer.buffer_data = (unsigned char *)&surface_param; 501 502 vtable->createContext(obj_context, NULL); 503 vtable->beginPicture(obj_context); 504 vtable->renderPicture(obj_context, &buffer_p, 1); 505 vtable->endPicture(obj_context); 506 vtable->destroyContext(obj_context); 507} 508