//Link a framebuffer to a surface in the current context static void attach_surface(EGLDisplay display, struct context *current, struct surface *surface) { if(!surface->buffer) { //An attached surface must have a buffer surface_dequeue_buffer(surface); LOGV("attach_surface - 1" ); if(surface->buffer) { LOGV("attach_surface - 2" ); attach_buffer( display, surface ); //yay LOGV("attach_surface - 3 (yay)" ); } else { LOGV("attach_surface() Failed to dequeue buffer: surface = %p, Thread = %d", surface, gettid()); } } else { LOGV("attach_surface() - already got buffer, so we are happy: surface = %p, Thread = %d", surface, gettid()); } surface->made_current = 1; }
static bool switch_frame(void *data, const void *frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char *msg, video_frame_info_t *video_info) { static uint64_t last_frame = 0; unsigned x, y; result_t r; int tgtw, tgth, centerx, centery; uint32_t *out_buffer = NULL; switch_video_t *sw = data; int xsf = 1280 / width; int ysf = 720 / height; int sf = xsf; if (ysf < sf) sf = ysf; tgtw = width * sf; tgth = height * sf; centerx = (1280-tgtw)/2; centery = (720-tgth)/2; // clear image to black for(y = 0; y < 720; y++) { for(x = 0; x < 1280; x++) { sw->image[y*1280+x] = 0xFF000000; } } if(width > 0 && height > 0) { if(sw->last_width != width || sw->last_height != height) { scaler_ctx_gen_reset(&sw->scaler); sw->scaler.in_width = width; sw->scaler.in_height = height; sw->scaler.in_stride = pitch; sw->scaler.in_fmt = sw->rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGB565; sw->scaler.out_width = tgtw; sw->scaler.out_height = tgth; sw->scaler.out_stride = 1280 * sizeof(uint32_t); sw->scaler.out_fmt = SCALER_FMT_ABGR8888; sw->scaler.scaler_type = SCALER_TYPE_POINT; if(!scaler_ctx_gen_filter(&sw->scaler)) { RARCH_ERR("failed to generate scaler for main image\n"); return false; } sw->last_width = width; sw->last_height = height; } scaler_ctx_scale(&sw->scaler, sw->image + (centery * 1280) + centerx, frame); } #if defined(HAVE_MENU) if (sw->menu_texture.enable) { menu_driver_frame(video_info); if (sw->menu_texture.pixels) { #if 0 if (sw->menu_texture.fullscreen) { #endif scaler_ctx_scale(&sw->menu_texture.scaler, sw->image + ((720-sw->menu_texture.tgth)/2)*1280 + ((1280-sw->menu_texture.tgtw)/2), sw->menu_texture.pixels); #if 0 } else { } #endif } } else if (video_info->statistics_show) { struct font_params *osd_params = (struct font_params*) &video_info->osd_stat_params; if (osd_params) { font_driver_render_msg(video_info, NULL, video_info->stat_text, (const struct font_params*)&video_info->osd_stat_params); } } #endif #if 0 if (frame_count > 6000) { display_finalize(); exit(0); } #endif if (msg && strlen(msg) > 0) RARCH_LOG("message: %s\n", msg); r = surface_dequeue_buffer(&sw->surface, &out_buffer); if (sw->vsync) switch_wait_vsync(sw); svcSleepThread(10000); if(r != RESULT_OK) { return true; // just skip the frame } gfx_slow_swizzling_blit(out_buffer, sw->image, 1280, 720, 0, 0); r = surface_queue_buffer(&sw->surface); if (r != RESULT_OK) return false; last_frame = svcGetSystemTick(); return true; }
EGLBoolean eglSwapBuffers(EGLDisplay display, EGLSurface surface_) { struct context *current_context = brcm_egl_get_current(); struct surface *surface = (struct surface *)surface_; if( !current_context ) { LOGE("eglSwapBuffers() - TODO - function called but no current context is valid"); return false; } //nothing bound? if(surface_ == EGL_NO_SURFACE) { LOGE("eglSwapBuffers(%p) error: EGL_BAD_SURFACE Thread: %d", current_context, gettid()); return EGL_FALSE; } //do we have an android native window already assigned to our egl context? if(surface->window) { //check that the context wasn't deleted //TODO - explain why this could occur #if 0 if(egl_is_context_lost(thread)) { thread->error = EGL_CONTEXT_LOST; LOGE("eglSwapBuffers(%p) error: EGL_CONTEXT_LOST, Thread: %d", current_context, gettid()); return EGL_FALSE; } #endif LOGD_IF(current_context->profiling, "eglSwapBuffers(%d, %p) %d", (int)display, (void *)surface, gettid()); //todo - add in invalidates here #ifndef BRCM_V3D_OPT glFinish(); #else glFinish(); glFlush(); if(surface->buffer->format == HAL_PIXEL_FORMAT_YCbCr_422_I) convert_to_yuv(current_context->composer,surface->buffer); #endif //TODO - if we don't get a buffer below, then v3d will have a pointer to memory that it can't write to anymore EGLint res = glGetError(); if (res == GL_OUT_OF_MEMORY) { LOGE("eglSwapBuffers Error 0x%x",res); return false; } //send the current buffer out surface_enqueue_buffer( surface); sync_composer(current_context->composer); //grab a new buffer and bind it to V3D if( !surface_dequeue_buffer(surface) ) LOGE("surface_dequeue_buffer FATAL error - no buffer to attach"); attach_buffer(display, surface); return EGL_TRUE; } else { LOGE("eglSwapBuffers called but no window bound!" ); } return EGL_FALSE; }