PP_Resource ppb_audio_get_current_config(PP_Resource audio) { struct pp_audio_s *a = pp_resource_acquire(audio, PP_RESOURCE_AUDIO); if (!a) { trace_error("%s, bad resource\n", __func__); return 0; } PP_Resource audio_config = pp_resource_allocate(PP_RESOURCE_AUDIO_CONFIG, a->instance); struct pp_audio_config_s *ac = pp_resource_acquire(audio_config, PP_RESOURCE_AUDIO_CONFIG); if (!ac) { trace_error("%s, resource allocation failure\n", __func__); audio_config = 0; goto err; } ac->sample_rate = a->sample_rate; ac->sample_frame_count = a->sample_frame_count; pp_resource_release(audio_config); err: pp_resource_release(audio); return audio_config; }
PP_Resource ppb_wheel_input_event_create(PP_Instance instance, PP_TimeTicks time_stamp, uint32_t modifiers, const struct PP_FloatPoint *wheel_delta, const struct PP_FloatPoint *wheel_ticks, PP_Bool scroll_by_page) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource input_event = pp_resource_allocate(PP_RESOURCE_INPUT_EVENT, pp_i); struct pp_input_event_s *ie = pp_resource_acquire(input_event, PP_RESOURCE_INPUT_EVENT); if (!ie) { trace_error("%s, can't allocate memory\n", __func__); return 0; } ie->event_class = PP_INPUTEVENT_CLASS_WHEEL; ie->time_stamp = time_stamp; ie->modifiers = modifiers; ie->wheel_delta.x = wheel_delta ? wheel_delta->x : 0; ie->wheel_delta.y = wheel_delta ? wheel_delta->y : 0; ie->wheel_ticks.x = wheel_ticks ? wheel_ticks->x : 0; ie->wheel_ticks.y = wheel_ticks ? wheel_ticks->y : 0; ie->scroll_by_page = scroll_by_page; pp_resource_release(input_event); return input_event; }
PP_Resource ppb_host_resolver_get_net_address_1_0(PP_Resource host_resolver, uint32_t index) { PP_Resource net_address = 0; struct pp_host_resolver_s *hr = pp_resource_acquire(host_resolver, PP_RESOURCE_HOST_RESOLVER); if (!hr) { trace_error("%s, bad resource\n", __func__); goto err_1; } if (index >= hr->addr_count) goto err_2; net_address = pp_resource_allocate(PP_RESOURCE_NET_ADDRESS, hr->instance); struct pp_net_address_s *na = pp_resource_acquire(net_address, PP_RESOURCE_NET_ADDRESS); if (!na) { trace_error("%s, resource allocation failed\n", __func__); goto err_2; } memcpy(&na->addr, &hr->addrs[index], sizeof(struct PP_NetAddress_Private)); pp_resource_release(net_address); err_2: pp_resource_release(host_resolver); err_1: return net_address; }
PP_Resource ppb_video_capture_create(PP_Instance instance) { const struct PPP_VideoCapture_Dev_0_1 *ppp_video_capture_dev; struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } ppp_video_capture_dev = ppp_get_interface(PPP_VIDEO_CAPTURE_DEV_INTERFACE_0_1); if (!ppp_video_capture_dev) { trace_error("%s, no viable %s\n", __func__, PPP_VIDEO_CAPTURE_DEV_INTERFACE_0_1); return 0; } PP_Resource video_capture = pp_resource_allocate(PP_RESOURCE_VIDEO_CAPTURE, pp_i); struct pp_video_capture_s *vc = pp_resource_acquire(video_capture, PP_RESOURCE_VIDEO_CAPTURE); if (!vc) { trace_error("%s, resource allocation failure\n", __func__); return 0; } vc->fd = -1; vc->ppp_video_capture_dev = ppp_video_capture_dev; pp_resource_release(video_capture); return video_capture; }
PP_Resource ppb_url_request_info_create(PP_Instance instance) { PP_Resource request_info = pp_resource_allocate(PP_RESOURCE_URL_REQUEST_INFO, instance); struct pp_url_request_info_s *ri = pp_resource_acquire(request_info, PP_RESOURCE_URL_REQUEST_INFO); ri->method = PP_METHOD_UNKNOWN; ri->url = NULL; ri->headers = NULL; ri->stream_to_file = PP_FALSE; ri->follow_redirects = PP_TRUE; ri->record_download_progress = PP_FALSE; ri->record_upload_progress = PP_FALSE; ri->custom_referrer_url = NULL; ri->allow_cross_origin_requests = PP_FALSE; ri->allow_credentials = PP_FALSE; ri->custom_content_transfer_encoding = NULL; ri->prefetch_buffer_upper_threshold = -1; ri->prefetch_buffer_lower_threshold = -1; ri->custom_user_agent = NULL; pp_resource_release(request_info); return request_info; }
PP_Resource ppb_image_data_create(PP_Instance instance, PP_ImageDataFormat format, const struct PP_Size *size, PP_Bool init_to_zero) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource image_data = pp_resource_allocate(PP_RESOURCE_IMAGE_DATA, pp_i); struct pp_image_data_s *id = pp_resource_acquire(image_data, PP_RESOURCE_IMAGE_DATA); if (!id) { trace_error("%s, failed to create image data resource\n", __func__); return 0; } id->format = format; id->width = size->width; id->height = size->height; id->stride = id->width * 4; (void)init_to_zero; // ignore flag, always clear memory id->data = calloc(id->stride * id->height, 1); if (!id->data) { pp_resource_release(image_data); ppb_core_release_resource(image_data); trace_error("%s, can't allocate memory for image\n", __func__); return 0; } id->cairo_surf = cairo_image_surface_create_for_data((void *)id->data, CAIRO_FORMAT_ARGB32, id->width, id->height, id->stride); pp_resource_release(image_data); return image_data; }
PP_Resource ppb_device_ref_create(PP_Instance instance, struct PP_Var name, struct PP_Var longname, PP_DeviceType_Dev type) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource device_ref = pp_resource_allocate(PP_RESOURCE_DEVICE_REF, pp_i); struct pp_device_ref_s *dr = pp_resource_acquire(device_ref, PP_RESOURCE_DEVICE_REF); if (!dr) { trace_error("%s, resource allocation failure\n", __func__); return 0; } // no type checking is perfomed as it's an internal function dr->name = ppb_var_add_ref2(name); dr->longname = ppb_var_add_ref2(longname); dr->type = type; pp_resource_release(device_ref); return device_ref; }
PP_Resource ppb_url_response_info_get_body_as_file_ref(PP_Resource response) { struct pp_url_response_info_s *ri = pp_resource_acquire(response,PP_RESOURCE_URL_RESPONSE_INFO); if (!ri) { trace_error("%s, bad resource\n", __func__); return 0; } struct pp_url_loader_s *ul = ri->url_loader; PP_Resource file_ref = pp_resource_allocate(PP_RESOURCE_FILE_REF, ri->instance); struct pp_file_ref_s *fr = pp_resource_acquire(file_ref, PP_RESOURCE_FILE_REF); if (!fr) { trace_error("%s, resource allocation failure\n", __func__); pp_resource_release(response); return 0; } fr->fd = dup(ul->fd); fr->type = PP_FILE_REF_TYPE_FD; pp_resource_release(file_ref); pp_resource_release(response); return file_ref; }
PP_Resource ppb_url_loader_get_response_info(PP_Resource loader) { struct pp_url_loader_s *ul = pp_resource_acquire(loader, PP_RESOURCE_URL_LOADER); if (!ul) { trace_error("%s, bad resource\n", __func__); return 0; } PP_Resource response_info = pp_resource_allocate(PP_RESOURCE_URL_RESPONSE_INFO, ul->instance); struct pp_url_response_info_s *ri = pp_resource_acquire(response_info, PP_RESOURCE_URL_RESPONSE_INFO); if (!ri) { trace_error("%s, resource allocation failure\n", __func__); pp_resource_release(loader); return 0; } pp_resource_ref(loader); ri->url_loader_id = loader; ri->url_loader = ul; pp_resource_release(response_info); pp_resource_release(loader); return response_info; }
PP_Resource ppb_url_request_info_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource request_info = pp_resource_allocate(PP_RESOURCE_URL_REQUEST_INFO, pp_i); struct pp_url_request_info_s *ri = pp_resource_acquire(request_info, PP_RESOURCE_URL_REQUEST_INFO); if (!ri) { trace_error("%s, resource allocation failure\n", __func__); return 0; } ri->method = PP_METHOD_UNKNOWN; ri->url = NULL; ri->headers = NULL; ri->stream_to_file = PP_FALSE; ri->follow_redirects = PP_TRUE; ri->record_download_progress = PP_FALSE; ri->record_upload_progress = PP_FALSE; ri->custom_referrer_url = NULL; ri->allow_cross_origin_requests = PP_FALSE; ri->allow_credentials = PP_FALSE; ri->custom_content_transfer_encoding = NULL; ri->prefetch_buffer_upper_threshold = -1; ri->prefetch_buffer_lower_threshold = -1; ri->custom_user_agent = NULL; ri->post_data = post_data_new(); pp_resource_release(request_info); return request_info; }
PP_Resource ppb_flash_menu_create(PP_Instance instance_id, const struct PP_Flash_Menu *menu_data) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance_id); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource flash_menu = pp_resource_allocate(PP_RESOURCE_FLASH_MENU, pp_i); if (pp_resource_get_type(flash_menu) != PP_RESOURCE_FLASH_MENU) { trace_error("%s, resource allocation failure\n", __func__); return 0; } struct flash_menu_create_param_s *p = g_slice_alloc0(sizeof(*p)); p->flash_menu = flash_menu; p->menu_data = menu_data; p->m_loop = ppb_message_loop_get_current(); p->depth = ppb_message_loop_get_depth(p->m_loop) + 1; ppb_message_loop_post_work_with_result(p->m_loop, PP_MakeCCB(flash_menu_create_comt, p), 0, PP_OK, p->depth, __func__); ppb_message_loop_run_nested(p->m_loop); g_slice_free1(sizeof(*p), p); return flash_menu; }
PP_Resource ppb_mouse_input_event_create(PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, PP_InputEvent_MouseButton mouse_button, const struct PP_Point *mouse_position, int32_t click_count, const struct PP_Point *mouse_movement) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource input_event = pp_resource_allocate(PP_RESOURCE_INPUT_EVENT, pp_i); struct pp_input_event_s *ie = pp_resource_acquire(input_event, PP_RESOURCE_INPUT_EVENT); if (!ie) { trace_error("%s, can't allocate memory\n", __func__); return 0; } ie->event_class = PP_INPUTEVENT_CLASS_MOUSE; ie->type = type; ie->time_stamp = time_stamp; ie->modifiers = modifiers; ie->mouse_button = mouse_button; ie->mouse_position.x = mouse_position ? mouse_position->x : 0; ie->mouse_position.y = mouse_position ? mouse_position->y : 0; ie->click_count = click_count; ie->mouse_movement.x = mouse_movement ? mouse_movement->x : 0; ie->mouse_movement.y = mouse_movement ? mouse_movement->y : 0; pp_resource_release(input_event); return input_event; }
PP_Resource ppb_keyboard_input_event_create_1_2(PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, uint32_t key_code, struct PP_Var character_text, struct PP_Var code) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource input_event = pp_resource_allocate(PP_RESOURCE_INPUT_EVENT, pp_i); struct pp_input_event_s *ie = pp_resource_acquire(input_event, PP_RESOURCE_INPUT_EVENT); if (!ie) { trace_error("%s, can't allocate memory\n", __func__); return 0; } ie->event_class = PP_INPUTEVENT_CLASS_KEYBOARD; ie->type = type; ie->time_stamp = time_stamp; ie->modifiers = modifiers; ie->key_code = key_code; ie->character_text = character_text; ie->code = code; ppb_var_add_ref(character_text); ppb_var_add_ref(code); pp_resource_release(input_event); return input_event; }
PP_Resource ppb_graphics2d_create(PP_Instance instance, const struct PP_Size *size, PP_Bool is_always_opaque) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource graphics_2d = pp_resource_allocate(PP_RESOURCE_GRAPHICS2D, pp_i); struct pp_graphics2d_s *g2d = pp_resource_acquire(graphics_2d, PP_RESOURCE_GRAPHICS2D); if (!g2d) { trace_error("%s, can't create graphics2d resource\n", __func__); return 0; } g2d->is_always_opaque = is_always_opaque; g2d->scale = config.device_scale; g2d->width = size->width; g2d->height = size->height; g2d->stride = 4 * size->width; g2d->scaled_width = g2d->width * g2d->scale + 0.5; g2d->scaled_height = g2d->height * g2d->scale + 0.5; g2d->scaled_stride = 4 * g2d->scaled_width; g2d->data = calloc(g2d->stride * g2d->height, 1); g2d->second_buffer = calloc(g2d->scaled_stride * g2d->scaled_height, 1); if (!g2d->data || !g2d->second_buffer) { trace_warning("%s, can't allocate memory\n", __func__); free_and_nullify(g2d->data); free_and_nullify(g2d->second_buffer); pp_resource_release(graphics_2d); ppb_core_release_resource(graphics_2d); return 0; } g2d->cairo_surf = cairo_image_surface_create_for_data((unsigned char *)g2d->data, CAIRO_FORMAT_ARGB32, g2d->width, g2d->height, g2d->stride); g2d->task_list = NULL; if (pp_i->is_transparent) { // we need XRender picture (which in turn requires X Pixmap) to alpha blend // our images with existing pixmap provided by the browser. This is only needed // is instance is transparent, therefore depth is always 32-bit. pthread_mutex_lock(&display.lock); g2d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g2d->scaled_width, g2d->scaled_height, 32); XFlush(display.x); g2d->xr_pict = XRenderCreatePicture(display.x, g2d->pixmap, display.pictfmt_argb32, 0, 0); g2d->gc = XCreateGC(display.x, g2d->pixmap, 0, 0); XFlush(display.x); pthread_mutex_unlock(&display.lock); } pp_resource_release(graphics_2d); return graphics_2d; }
static PP_Resource do_ppb_audio_create(PP_Instance instance, PP_Resource audio_config, PPB_Audio_Callback_1_0 audio_callback_1_0, PPB_Audio_Callback audio_callback_1_1, void *user_data) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } if (!audio_callback_1_0 && !audio_callback_1_1) return PP_ERROR_BADARGUMENT; PP_Resource audio = pp_resource_allocate(PP_RESOURCE_AUDIO, pp_i); struct pp_audio_s *a = pp_resource_acquire(audio, PP_RESOURCE_AUDIO); if (!a) { trace_error("%s, resource allocation failure\n", __func__); return 0; } struct pp_audio_config_s *ac = pp_resource_acquire(audio_config, PP_RESOURCE_AUDIO_CONFIG); if (!ac) { trace_error("%s, bad audio config\n", __func__); goto err; } a->sample_rate = ac->sample_rate; a->sample_frame_count = ac->sample_frame_count; pp_resource_release(audio_config); a->callback_1_0 = audio_callback_1_0; a->callback_1_1 = audio_callback_1_1; a->user_data = user_data; a->stream_ops = audio_select_implementation(); if (a->stream_ops == NULL) { trace_error("%s, no viable audio implementation\n", __func__); goto err; } a->stream = a->stream_ops->create_playback_stream(a->sample_rate, a->sample_frame_count, playback_cb, a); if (!a->stream) { trace_error("%s, can't create playback stream\n", __func__); goto err; } pp_resource_release(audio); return audio; err: pp_resource_release(audio); pp_resource_expunge(audio); return 0; }
PP_Resource ppb_network_monitor_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource network_monitor = pp_resource_allocate(PP_RESOURCE_NETWORK_MONITOR, pp_i); return network_monitor; }
PP_Resource ppb_flash_message_loop_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource message_loop = pp_resource_allocate(PP_RESOURCE_FLASH_MESSAGE_LOOP, pp_i); return message_loop; }
PP_Resource ppb_printing_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource printing = pp_resource_allocate(PP_RESOURCE_PRINTING, pp_i); return printing; }
PP_Resource ppb_host_resolver_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource host_resolver = pp_resource_allocate(PP_RESOURCE_HOST_RESOLVER, pp_i); return host_resolver; }
PP_Resource ppb_audio_config_create_stereo_16_bit(PP_Instance instance, PP_AudioSampleRate sample_rate, uint32_t sample_frame_count) { PP_Resource audio_config = pp_resource_allocate(PP_RESOURCE_AUDIO_CONFIG, instance); struct pp_audio_config_s *ac = pp_resource_acquire(audio_config, PP_RESOURCE_AUDIO_CONFIG); ac->sample_rate = sample_rate; ac->sample_frame_count = clamp_value(sample_frame_count, PP_AUDIOMINSAMPLEFRAMECOUNT, PP_AUDIOMAXSAMPLEFRAMECOUNT); pp_resource_release(audio_config); return audio_config; }
PP_Resource ppb_browser_font_trusted_create(PP_Instance instance, const struct PP_BrowserFont_Trusted_Description *description) { PP_Resource font = pp_resource_allocate(PP_RESOURCE_BROWSER_FONT, instance); struct pp_browser_font_s *bf = pp_resource_acquire(font, PP_RESOURCE_BROWSER_FONT); PangoFontDescription *font_desc = pp_font_desc_to_pango_font_desc(description); bf->family = description->face.type == PP_VARTYPE_STRING ? -1 : description->family; bf->letter_spacing = description->letter_spacing; bf->word_spacing = description->word_spacing; bf->font = pango_context_load_font(tables_get_pango_ctx(), font_desc); bf->font_desc = pango_font_describe_with_absolute_size(bf->font); pango_font_description_free(font_desc); pp_resource_release(font); return font; }
PP_Resource ppb_flash_drm_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource flash_drm = pp_resource_allocate(PP_RESOURCE_FLASH_DRM, pp_i); struct pp_flash_drm_s *fd = pp_resource_acquire(flash_drm, PP_RESOURCE_FLASH_DRM); if (!fd) { trace_error("%s, failed to create flash drm resource\n", __func__); return 0; } pp_resource_release(flash_drm); return flash_drm; }
PP_Resource ppb_ime_input_event_create(PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, struct PP_Var text, uint32_t segment_number, const uint32_t segment_offsets[], int32_t target_segment, uint32_t selection_start, uint32_t selection_end) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } if (type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_START && type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE && type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_END && type != PP_INPUTEVENT_TYPE_IME_TEXT) { trace_warning("%s, wrong type=%d\n", __func__, type); return 0; } PP_Resource input_event = pp_resource_allocate(PP_RESOURCE_INPUT_EVENT, pp_i); struct pp_input_event_s *ie = pp_resource_acquire(input_event, PP_RESOURCE_INPUT_EVENT); if (!ie) { trace_error("%s, can't allocate memory\n", __func__); return 0; } ie->event_class = PP_INPUTEVENT_CLASS_IME; ie->type = type; ie->time_stamp = time_stamp; ie->text = ppb_var_add_ref2(text); ie->segment_number = segment_number; ie->segment_offsets = NULL; if (segment_number > 0) { ie->segment_offsets = malloc((segment_number + 1) * sizeof(uint32_t)); memcpy(ie->segment_offsets, segment_offsets, (segment_number + 1) * sizeof(uint32_t)); } ie->target_segment = target_segment; ie->selection_start = selection_start; ie->selection_end = selection_end; pp_resource_release(input_event); return input_event; }
PP_Resource ppb_tcp_socket_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource tcp_socket = pp_resource_allocate(PP_RESOURCE_TCP_SOCKET, pp_i); struct pp_tcp_socket_s *ts = pp_resource_acquire(tcp_socket, PP_RESOURCE_TCP_SOCKET); if (!ts) { trace_error("%s, resource allocation failure\n", __func__); return 0; } ts->sock = socket(AF_INET, SOCK_STREAM, 0); pp_resource_release(tcp_socket); return tcp_socket; }
PP_Resource ppb_graphics2d_create(PP_Instance instance, const struct PP_Size *size, PP_Bool is_always_opaque) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource graphics_2d = pp_resource_allocate(PP_RESOURCE_GRAPHICS2D, pp_i); struct pp_graphics2d_s *g2d = pp_resource_acquire(graphics_2d, PP_RESOURCE_GRAPHICS2D); if (!g2d) { trace_error("%s, can't create graphics2d resource\n", __func__); return 0; } g2d->is_always_opaque = is_always_opaque; g2d->scale = 1.0; g2d->width = size->width; g2d->height = size->height; g2d->stride = 4 * size->width; g2d->scaled_width = g2d->width; g2d->scaled_height = g2d->height; g2d->scaled_stride = g2d->stride; g2d->data = calloc(g2d->stride * g2d->height, 1); g2d->second_buffer = calloc(g2d->scaled_stride * g2d->scaled_height, 1); if (!g2d->data || !g2d->second_buffer) { trace_warning("%s, can't allocate memory\n", __func__); free_and_nullify(g2d, data); free_and_nullify(g2d, second_buffer); pp_resource_release(graphics_2d); ppb_core_release_resource(graphics_2d); return 0; } g2d->cairo_surf = cairo_image_surface_create_for_data((unsigned char *)g2d->data, CAIRO_FORMAT_ARGB32, g2d->width, g2d->height, g2d->stride); g2d->task_list = NULL; pp_resource_release(graphics_2d); return graphics_2d; }
PP_Resource ppb_font_create(PP_Instance instance, const struct PP_FontDescription_Dev *description) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource font = pp_resource_allocate(PP_RESOURCE_FONT, pp_i); struct pp_font_s *f = pp_resource_acquire(font, PP_RESOURCE_FONT); if (!f) { trace_error("%s, resource allocation failure\n", __func__); return 0; } fpp_font_init(&f->ff, description); pp_resource_release(font); return font; }
PP_Resource ppb_message_loop_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, wrong instance\n", __func__); return 0; } PP_Resource message_loop = pp_resource_allocate(PP_RESOURCE_MESSAGE_LOOP, pp_i); struct pp_message_loop_s *ml = pp_resource_acquire(message_loop, PP_RESOURCE_MESSAGE_LOOP); if (!ml) { trace_error("%s, resource allocation failure\n", __func__); return 0; } ml->async_q = g_async_queue_new(); ml->int_q = g_queue_new(); ml->depth = 1; pp_resource_release(message_loop); return message_loop; }
PP_Resource ppb_url_loader_create(PP_Instance instance) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource url_loader = pp_resource_allocate(PP_RESOURCE_URL_LOADER, pp_i); struct pp_url_loader_s *ul = pp_resource_acquire(url_loader, PP_RESOURCE_URL_LOADER); if (!ul) { trace_error("%s, resource allocation failure\n", __func__); return 0; } // all fields are zeroed by default ul->response_size = -1; ul->method = PP_METHOD_GET; ul->fd = -1; pp_resource_release(url_loader); return url_loader; }
PP_Resource ppb_graphics3d_create(PP_Instance instance, PP_Resource share_context, const int32_t attrib_list[]) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } PP_Resource context = pp_resource_allocate(PP_RESOURCE_GRAPHICS3D, pp_i); struct pp_graphics3d_s *g3d = pp_resource_acquire(context, PP_RESOURCE_GRAPHICS3D); if (!g3d) { trace_error("%s, can't create context\n", __func__); return 0; } int attrib_len = 0; while (attrib_list[attrib_len] != PP_GRAPHICS3DATTRIB_NONE) { attrib_len += 2; } attrib_len ++; EGLint *egl_attribute_list = calloc(attrib_len + 3 * 2, sizeof(EGLint)); int done = 0, k1 = 0, k2 = 0; egl_attribute_list[k2++] = EGL_SURFACE_TYPE; egl_attribute_list[k2++] = EGL_PIXMAP_BIT | EGL_WINDOW_BIT; egl_attribute_list[k2++] = EGL_RENDERABLE_TYPE; egl_attribute_list[k2++] = EGL_OPENGL_ES2_BIT; while (!done) { switch (attrib_list[k1]) { case PP_GRAPHICS3DATTRIB_HEIGHT: g3d->height = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_WIDTH: g3d->width = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE: case PP_GRAPHICS3DATTRIB_SWAP_BEHAVIOR: // TODO: save these values k1 += 2; break; case PP_GRAPHICS3DATTRIB_NONE: egl_attribute_list[k2++] = EGL_NONE; done = 1; break; case PP_GRAPHICS3DATTRIB_ALPHA_SIZE: egl_attribute_list[k2++] = EGL_ALPHA_SIZE; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_BLUE_SIZE: egl_attribute_list[k2++] = EGL_BLUE_SIZE; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_GREEN_SIZE: egl_attribute_list[k2++] = EGL_GREEN_SIZE; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_RED_SIZE: egl_attribute_list[k2++] = EGL_RED_SIZE; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_DEPTH_SIZE: egl_attribute_list[k2++] = EGL_DEPTH_SIZE; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_STENCIL_SIZE: egl_attribute_list[k2++] = EGL_STENCIL_SIZE; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_SAMPLES: egl_attribute_list[k2++] = EGL_SAMPLES; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS: egl_attribute_list[k2++] = EGL_SAMPLE_BUFFERS; egl_attribute_list[k2++] = attrib_list[k1 + 1]; k1 += 2; break; default: // skip unknown attribute trace_error("%s, unknown attribute 0x%x\n", __func__, attrib_list[k1]); k1 += 1; break; } } pthread_mutex_lock(&display.lock); int nconfigs = 0; EGLBoolean ret = eglChooseConfig(display.egl, egl_attribute_list, &g3d->egl_config, 1, &nconfigs); free(egl_attribute_list); if (!ret) { trace_error("%s, eglChooseConfig returned FALSE\n", __func__); goto err; } if (nconfigs != 1) { trace_error("%s, eglChooseConfig returned %d configs, expected 1\n", __func__, nconfigs); goto err; } // TODO: support shared_context EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; g3d->glc = eglCreateContext(display.egl, g3d->egl_config, EGL_NO_CONTEXT, ctxattr); if (g3d->glc == EGL_NO_CONTEXT) { trace_error("%s, eglCreateContext returned EGL_NO_CONTEXT\n", __func__); goto err; } g3d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g3d->width, g3d->height, DefaultDepth(display.x, 0)); g3d->egl_surf = eglCreatePixmapSurface(display.egl, g3d->egl_config, g3d->pixmap, NULL); if (g3d->egl_surf == EGL_NO_SURFACE) { trace_error("%s, failed to create EGL pixmap surface\n", __func__); goto err; } ret = eglMakeCurrent(display.egl, g3d->egl_surf, g3d->egl_surf, g3d->glc); if (!ret) { trace_error("%s, eglMakeCurrent failed\n", __func__); goto err; } // clear surface glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (pp_i->is_transparent) { // create texture for plugin content glGenTextures(1, &g3d->tex_front); glBindTexture(GL_TEXTURE_2D, g3d->tex_front); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); if (create_presentation_egl_context(g3d) != 0) { trace_error("%s, can't create EGL context for transparency processing\n", __func__); goto err; } } eglMakeCurrent(display.egl, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); g3d->sub_maps = g_hash_table_new(g_direct_hash, g_direct_equal); pthread_mutex_unlock(&display.lock); pp_resource_release(context); return context; err: pthread_mutex_unlock(&display.lock); pp_resource_release(context); pp_resource_expunge(context); return 0; }
PP_Resource ppb_graphics3d_create(PP_Instance instance, PP_Resource share_context, const int32_t attrib_list[]) { struct pp_instance_s *pp_i = tables_get_pp_instance(instance); if (!pp_i) { trace_error("%s, bad instance\n", __func__); return 0; } GLXContext share_glc = (share_context == 0) ? NULL : peek_gl_context(share_context); // check for required GLX extensions #if HAVE_GLES2 if (!display.glx_arb_create_context || !display.glx_arb_create_context_profile || !display.glx_ext_create_context_es2_profile) { trace_warning("%s, some of GLX_ARB_create_context, GLX_ARB_create_context_profile, " "GLX_EXT_create_context_es2_profile missing\n", __func__); return 0; } if (!display.glXCreateContextAttribsARB) { trace_warning("%s, no glXCreateContextAttribsARB found\n", __func__); return 0; } #endif PP_Resource context = pp_resource_allocate(PP_RESOURCE_GRAPHICS3D, pp_i); struct pp_graphics3d_s *g3d = pp_resource_acquire(context, PP_RESOURCE_GRAPHICS3D); if (!g3d) { trace_error("%s, can't create context\n", __func__); return 0; } int attrib_len = 0; while (attrib_list[attrib_len] != PP_GRAPHICS3DATTRIB_NONE) { attrib_len += 2; } attrib_len ++; int *cfg_attrs = calloc(attrib_len + 3 * 2, sizeof(int)); int k2 = 0; cfg_attrs[k2++] = GLX_X_RENDERABLE; cfg_attrs[k2++] = True; cfg_attrs[k2++] = GLX_DRAWABLE_TYPE; cfg_attrs[k2++] = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; int done = 0; int k1 = 0; while (!done) { switch (attrib_list[k1]) { case PP_GRAPHICS3DATTRIB_HEIGHT: g3d->height = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_WIDTH: g3d->width = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE: case PP_GRAPHICS3DATTRIB_SWAP_BEHAVIOR: // TODO: save these values k1 += 2; break; case PP_GRAPHICS3DATTRIB_NONE: cfg_attrs[k2++] = None; done = 1; break; case PP_GRAPHICS3DATTRIB_ALPHA_SIZE: cfg_attrs[k2++] = GLX_ALPHA_SIZE; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_BLUE_SIZE: cfg_attrs[k2++] = GLX_BLUE_SIZE; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_GREEN_SIZE: cfg_attrs[k2++] = GLX_GREEN_SIZE; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_RED_SIZE: cfg_attrs[k2++] = GLX_RED_SIZE; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_DEPTH_SIZE: cfg_attrs[k2++] = GLX_DEPTH_SIZE; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_STENCIL_SIZE: cfg_attrs[k2++] = GLX_STENCIL_SIZE; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_SAMPLES: cfg_attrs[k2++] = GLX_SAMPLES; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS: cfg_attrs[k2++] = GLX_SAMPLE_BUFFERS; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case GLX_Y_INVERTED_EXT: cfg_attrs[k2++] = GLX_Y_INVERTED_EXT; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; case GLX_BIND_TO_TEXTURE_RGBA_EXT: cfg_attrs[k2++] = GLX_BIND_TO_TEXTURE_RGBA_EXT; cfg_attrs[k2++] = attrib_list[k1 + 1]; k1 += 2; break; default: // skip unknown attribute trace_error("%s, unknown attribute 0x%x\n", __func__, attrib_list[k1]); k1 += 1; break; } } pthread_mutex_lock(&display.lock); int screen = DefaultScreen(display.x); int nconfigs = 0; GLXFBConfig *fb_cfgs = glXChooseFBConfig(display.x, screen, cfg_attrs, &nconfigs); free(cfg_attrs); if (!fb_cfgs) { trace_error("%s, glXChooseFBConfig returned NULL\n", __func__); goto err; } trace_info_f("%s, glXChooseFBConfig returned %d configs, choosing first one\n", __func__, nconfigs); g3d->fb_config = fb_cfgs[0]; XFree(fb_cfgs); #if HAVE_GLES2 // create context implementing OpenGL ES 2.0 const int ctx_attrs[] = { GLX_RENDER_TYPE, GLX_RGBA_TYPE, GLX_CONTEXT_MAJOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 0, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, None, }; #else // create context implementing OpenGL 2.0 // OpenGL ES 2.0 will be emulated with help of shader translator const int ctx_attrs[] = { GLX_RENDER_TYPE, GLX_RGBA_TYPE, GLX_CONTEXT_MAJOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None, }; #endif if (display.glXCreateContextAttribsARB) { g3d->glc = display.glXCreateContextAttribsARB(display.x, g3d->fb_config, share_glc, True, ctx_attrs); if (!g3d->glc) trace_warning("%s, glXCreateContextAttribsARB returned NULL\n", __func__); } else { g3d->glc = NULL; } if (!g3d->glc) { // if glXCreateContextAttribsARB is not present or returned NULL, // request any GL context g3d->glc = glXCreateNewContext(display.x, g3d->fb_config, GLX_RGBA_TYPE, share_glc, True); if (!g3d->glc) { trace_error("%s, glXCreateNewContext returned NULL\n", __func__); goto err; } } g3d->depth = pp_i->is_transparent ? 32 : DefaultDepth(display.x, screen); switch (g3d->depth) { case 24: g3d->xr_pictfmt = display.pictfmt_rgb24; break; case 32: g3d->xr_pictfmt = display.pictfmt_argb32; break; default: trace_error("%s, unsupported g3d->depth (%d)\n", __func__, g3d->depth); goto err; } g3d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g3d->width, g3d->height, g3d->depth); g3d->glx_pixmap = glXCreatePixmap(display.x, g3d->fb_config, g3d->pixmap, NULL); if (g3d->glx_pixmap == None) { trace_error("%s, failed to create GLX pixmap\n", __func__); goto err; } XFlush(display.x); g3d->xr_pict = XRenderCreatePicture(display.x, g3d->pixmap, g3d->xr_pictfmt, 0, 0); int ret = glXMakeCurrent(display.x, g3d->glx_pixmap, g3d->glc); if (!ret) { trace_error("%s, glXMakeCurrent failed\n", __func__); goto err; } // clear surface glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glXMakeCurrent(display.x, None, NULL); g3d->sub_maps = g_hash_table_new(g_direct_hash, g_direct_equal); pthread_mutex_unlock(&display.lock); pp_resource_release(context); return context; err: pthread_mutex_unlock(&display.lock); pp_resource_release(context); pp_resource_expunge(context); return 0; }