{
Evas_Native_Surface *ns;
ns = ENFN->image_native_get(ENDT, o->engine_data);
- if ( (ns) &&
- (ns->type == EVAS_NATIVE_SURFACE_OPENGL) &&
- (ns->data.opengl.texture_id) &&
- (!ns->data.opengl.framebuffer_id) )
+ if (ns)
{
Eina_Bool direct_renderable = EINA_FALSE;
{
if ((ENFN->gl_get_pixels_set) && (o->pixels->func.get_pixels))
ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj);
+ if (ENFN->gl_image_direct_set)
+ ENFN->gl_image_direct_set(output, o->engine_data, EINA_TRUE);
o->direct_render = EINA_TRUE;
}
else
else
{
// Check if the it's not dirty but it has direct rendering
- if (o->direct_render)
+ if (o->direct_render && ENFN->image_native_get)
{
- ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj);
+ Evas_Native_Surface *ns;
+ ns = ENFN->image_native_get(output, o->engine_data);
+ if (ENFN->gl_direct_override_get)
+ ENFN->gl_direct_override_get(output, &direct_override, &direct_force_off);
+ if (ENFN->gl_surface_direct_renderable_get)
+ ENFN->gl_surface_direct_renderable_get(output, ns, &direct_override);
+
+ if (direct_override && !direct_force_off)
+ {
+ // always use direct rendering
+ if (ENFN->gl_get_pixels_set)
+ ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj);
+ if (ENFN->gl_image_direct_set)
+ ENFN->gl_image_direct_set(output, o->engine_data, EINA_TRUE);
+ }
+ else
+ {
+ // Auto-fallback to FBO rendering (for perf & power consumption)
+ o->pixels->func.get_pixels(o->pixels->func.get_pixels_data, obj->object);
+ //if (ENFN->get_pixels_render_post)
+ //ENFN->get_pixels_render_post(output);
+ o->direct_render = EINA_FALSE;
+ }
}
}
ENFN->context_render_op_set(output, context, obj->cur->render_op);
// Clear out the pixel get stuff..
- if ((ENFN->gl_get_pixels_set) && (o->pixels->func.get_pixels))
- {
- ENFN->gl_get_pixels_set(output, NULL, NULL, NULL);
- }
+ if (ENFN->gl_get_pixels_set)
+ ENFN->gl_get_pixels_set(output, NULL, NULL, NULL);
+ if (ENFN->gl_image_direct_set)
+ ENFN->gl_image_direct_set(output, o->engine_data, EINA_FALSE);
Evas_Object_Protected_Data *source =
(o->cur->source ?
if (sfc->direct_fb_opt)
{
- eina_hash_add(evgl_engine->direct_surfaces, &sfc->color_buf, sfc);
- DBG("Added tex %d as direct surface: %p", sfc->color_buf, sfc);
+ if (!sfc->gles1_indirect)
+ {
+ eina_hash_add(evgl_engine->direct_surfaces, &sfc->color_buf, sfc);
+ DBG("Added tex %d as direct surface: %p", sfc->color_buf, sfc);
+ }
+ else
+ {
+ eina_hash_add(evgl_engine->direct_surfaces, &sfc->gles1_sfc_native, sfc);
+ DBG("Added tex %d as direct surface: %p", sfc->gles1_sfc_native, sfc);
+ }
}
if (sfc->direct_fb_opt &&
}
}
+ // Do a make current
+ if (!_internal_resource_make_current(eng_data, ctx))
+ {
+ ERR("Error doing a make current with internal surface. Context: %p", ctx);
+ evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
+ return 0;
+ }
+
if (ctx->version == EVAS_GL_GLES_1_X)
{
if (dbg) DBG("ctx %p is GLES 1", ctx);
if (_evgl_direct_renderable(rsc, sfc))
{
- if (dbg) DBG("sfc %p is direct renderable.", sfc);
- // Do a make current
- if (!_internal_resource_make_current(eng_data, ctx))
+ // Transition from pixmap surface rendering to direct rendering
+ if (!rsc->direct.rendered)
{
- ERR("Error doing a make current with internal surface. Context: %p", ctx);
- evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
- return 0;
+ // Restore viewport and scissor test to direct rendering mode
+ glViewport(ctx->viewport_direct[0], ctx->viewport_direct[1], ctx->viewport_direct[2], ctx->viewport_direct[3]);
+ if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
+ glEnable(GL_SCISSOR_TEST);
}
+ if (dbg) DBG("sfc %p is direct renderable.", sfc);
rsc->direct.rendered = 1;
}
else
ERR("Failed to make current with GLES1 indirect surface.");
return 0;
}
- }
-
- ctx->current_sfc = sfc;
- rsc->current_ctx = ctx;
- rsc->current_eng = eng_data;
-
- // Update extensions after GLESv1 context is bound
- //evgl_api_gles1_ext_get(gles1_funcs);
-
- _surface_context_list_print();
- return 1;
- }
+ // Transition from direct rendering to pixmap surface rendering
+ if (rsc->direct.rendered)
+ {
+ glViewport(ctx->viewport_coord[0], ctx->viewport_coord[1], ctx->viewport_coord[2], ctx->viewport_coord[3]);
+ if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
+ glDisable(GL_SCISSOR_TEST);
+ }
- // Do a make current
- if (!_internal_resource_make_current(eng_data, ctx))
- {
- ERR("Error doing a make current with internal surface. Context: %p", ctx);
- evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
- return 0;
+ ctx->current_fbo = 0;
+ rsc->direct.rendered = 0;
+ }
}
-
- // Normal FBO Rendering
- // Create FBO if it hasn't been created
- if (!ctx->surface_fbo)
- glGenFramebuffers(1, &ctx->surface_fbo);
-
- // Direct Rendering
- if (_evgl_direct_renderable(rsc, sfc))
+ else // gles 2.x and 3.x
{
- if (dbg) DBG("sfc %p is direct renderable.", sfc);
+ // Normal FBO Rendering
+ // Create FBO if it hasn't been created
+ if (!ctx->surface_fbo)
+ glGenFramebuffers(1, &ctx->surface_fbo);
- // This is to transition from FBO rendering to direct rendering
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
- if (ctx->surface_fbo == (GLuint)curr_fbo)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- ctx->current_fbo = 0;
- }
- else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
+ // Direct Rendering
+ if (_evgl_direct_renderable(rsc, sfc))
{
- // Using the same context, we were rendering on a pbuffer
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- ctx->current_fbo = 0;
- }
+ if (dbg) DBG("sfc %p is direct renderable.", sfc);
- if (ctx->current_fbo == 0)
- {
- // If master clip is set and clip is greater than 0, do partial render
- if (rsc->direct.partial.enabled)
+ // This is to transition from FBO rendering to direct rendering
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
+ if (ctx->surface_fbo == (GLuint)curr_fbo)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ ctx->current_fbo = 0;
+ }
+ else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
+ {
+ // Using the same context, we were rendering on a pbuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ ctx->current_fbo = 0;
+ }
+
+ if (ctx->current_fbo == 0)
{
- if (!ctx->partial_render)
+ // If master clip is set and clip is greater than 0, do partial render
+ if (rsc->direct.partial.enabled)
{
- evgl_direct_partial_render_start();
- ctx->partial_render = 1;
+ if (!ctx->partial_render)
+ {
+ evgl_direct_partial_render_start();
+ ctx->partial_render = 1;
+ }
}
}
- }
-
- rsc->direct.rendered = 1;
- }
- else if (sfc->pbuffer.native_surface)
- {
- if (dbg) DBG("Surface sfc %p is a pbuffer: %p", sfc, sfc->pbuffer.native_surface);
-
- // Call end tiling
- if (rsc->direct.partial.enabled)
- evgl_direct_partial_render_end();
- if (sfc->color_buf)
- {
- if (!_surface_buffers_fbo_set(sfc, sfc->color_buf))
- ERR("Could not detach current FBO");
+ rsc->direct.rendered = 1;
}
-
- if (dbg) DBG("Calling make_current(%p, %p)", sfc->pbuffer.native_surface, ctx->context);
- evgl_engine->funcs->make_current(eng_data, sfc->pbuffer.native_surface,
- ctx->context, EINA_TRUE);
-
- // Bind to the previously bound buffer (may be 0)
- if (ctx->current_fbo)
+ else if (sfc->pbuffer.native_surface)
{
- glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
- GLERRLOG();
- }
+ if (dbg) DBG("Surface sfc %p is a pbuffer: %p", sfc, sfc->pbuffer.native_surface);
- rsc->direct.rendered = 0;
- }
- else
- {
- if (dbg) DBG("Surface sfc %p is a normal surface.", sfc);
+ // Call end tiling
+ if (rsc->direct.partial.enabled)
+ evgl_direct_partial_render_end();
- // Attach fbo and the buffers
- if ((ctx->current_sfc != sfc) || (ctx != sfc->current_ctx))
- {
- sfc->current_ctx = ctx;
- if ((sfc->direct_mem_opt) && (sfc->direct_fb_opt))
+ if (sfc->color_buf)
{
- DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
+ if (!_surface_buffers_fbo_set(sfc, sfc->color_buf))
+ ERR("Could not detach current FBO");
}
- else
+
+ if (dbg) DBG("Calling make_current(%p, %p)", sfc->pbuffer.native_surface, ctx->context);
+ evgl_engine->funcs->make_current(eng_data, sfc->pbuffer.native_surface,
+ ctx->context, EINA_TRUE);
+
+ // Bind to the previously bound buffer (may be 0)
+ if (ctx->current_fbo)
{
- // If it's transitioning from direct render to fbo render
- // Call end tiling
- if (rsc->direct.partial.enabled)
- evgl_direct_partial_render_end();
+ glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
+ GLERRLOG();
+ }
- if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo))
+ rsc->direct.rendered = 0;
+ }
+ else
+ {
+ if (dbg) DBG("Surface sfc %p is a normal surface.", sfc);
+
+ // Attach fbo and the buffers
+ if ((rsc->current_ctx != ctx) || (ctx->current_sfc != sfc) || (rsc->direct.rendered))
+ {
+ sfc->current_ctx = ctx;
+ if ((sfc->direct_mem_opt) && (sfc->direct_fb_opt))
{
- ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo);
- evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
- return 0;
+ DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
}
- }
+ else
+ {
+ // If it's transitioning from direct render to fbo render
+ // Call end tiling
+ if (rsc->direct.partial.enabled)
+ evgl_direct_partial_render_end();
- // Bind to the previously bound buffer
- if (ctx->current_fbo)
- glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
+ if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo))
+ {
+ ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo);
+ evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
+ return 0;
+ }
+ }
+
+ // Bind to the previously bound buffer
+ if (ctx->current_fbo)
+ glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
+ }
+ rsc->direct.rendered = 0;
}
- rsc->direct.rendered = 0;
}
ctx->current_sfc = sfc;
return 0;
}
- if (!sfc->xpixmap || sfc->direct_fb_opt)
+ if (!sfc->gles1_indirect)
{
ns->type = EVAS_NATIVE_SURFACE_OPENGL;
ns->version = EVAS_NATIVE_SURFACE_VERSION;
ns->data.opengl.y = 0;
ns->data.opengl.w = sfc->w;
ns->data.opengl.h = sfc->h;
-
- if (sfc->direct_fb_opt)
- ns->data.opengl.framebuffer_id = 0;
}
else
{
if (client_side_rotation) *client_side_rotation = EINA_FALSE;
if (!evgl_engine) return EINA_FALSE;
- if (!ns || (ns->type != EVAS_NATIVE_SURFACE_OPENGL)) return EINA_FALSE;
- if (ns->data.opengl.framebuffer_id != 0) return EINA_FALSE;
- if (ns->data.opengl.texture_id == 0) return EINA_FALSE;
+ if (!ns) return EINA_FALSE;
- sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.opengl.texture_id);
- if (!sfc)
+ if (ns->type == EVAS_NATIVE_SURFACE_OPENGL &&
+ ns->data.opengl.texture_id)
+ {
+ sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.opengl.texture_id);
+ if (!sfc)
+ {
+ DBG("Native surface %p (color_buf %d) was not found.",
+ ns, ns->data.opengl.texture_id);
+ return EINA_FALSE;
+ }
+ }
+ else if (ns->type == EVAS_NATIVE_SURFACE_X11 &&
+ ns->data.x11.pixmap)
+ {
+ sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.x11.pixmap);
+ if (!sfc)
+ {
+ DBG("Native surface %p (pixmap %x) was not found.",
+ ns, ns->data.x11.pixmap);
+ return EINA_FALSE;
+ }
+ }
+ else
{
- DBG("Native surface %p (color_buf %d) was not found.",
- ns, ns->data.opengl.texture_id);
+ ERR("Only EVAS_NATIVE_SURFACE_OPENGL or EVAS_NATIVE_SURFACE_X11 can be used for direct rendering");
return EINA_FALSE;
}
if (evgl_engine->api_debug_mode)
{
- DBG("Found native surface: texid:%u DR:%d DORR:%d CSR:%d",
- ns->data.opengl.texture_id, (int) sfc->direct_fb_opt,
- (int) sfc->direct_override, (int) sfc->client_side_rotation);
+ DBG("Found native surface: DR:%d CSR:%d",
+ (int) sfc->direct_fb_opt, (int) sfc->client_side_rotation);
}
if (direct_render) *direct_render = sfc->direct_fb_opt;
- if (direct_override) *direct_override = sfc->direct_override;
+ if (direct_override) *direct_override |= sfc->direct_override;
if (client_side_rotation) *client_side_rotation = sfc->client_side_rotation;
return EINA_TRUE;
}
static int _evas_engine_GL_log_dom = -1;
+static int eng_gl_image_direct_get(void *data EINA_UNUSED, void *image);
+
static void
eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h, Eina_Bool do_async EINA_UNUSED)
{
gl_context = re->window_gl_context_get(re->software.ob);
re->window_use(re->software.ob);
- if ((n) && (n->type == EVAS_NATIVE_SURFACE_OPENGL) &&
- (n->data.opengl.framebuffer_id == 0) &&
- re->func.get_pixels)
+ if (eng_gl_image_direct_get(data, image))
{
+ unsigned int texid;
+
gl_context->dc = context;
if ((gl_context->master_clip.enabled) &&
(gl_context->master_clip.w > 0) &&
evgl_direct_partial_info_set(gl_context->preserve_bit);
}
+ if (n->type == EVAS_NATIVE_SURFACE_OPENGL)
+ texid = n->data.opengl.texture_id;
+ else if (n->type == EVAS_NATIVE_SURFACE_X11)
+ texid = n->data.x11.pixmap;
+ else
+ {
+ ERR("This native surface type is not supported for direct rendering");
+ return EINA_FALSE;
+ }
+
// Set necessary info for direct rendering
evgl_direct_info_set(gl_context->w,
gl_context->h,
gl_context->dc->clip.y,
gl_context->dc->clip.w,
gl_context->dc->clip.h,
- n->data.opengl.texture_id);
+ texid);
// Call pixel get function
re->func.get_pixels(re->func.get_pixels_data, re->func.obj);
#endif
}
+static int
+eng_gl_image_direct_get(void *data EINA_UNUSED, void *image)
+{
+ Evas_GL_Image *im = image;
+ if (!im) return EINA_FALSE;
+ return im->direct;
+}
+
+static void
+eng_gl_image_direct_set(void *data, void *image, Eina_Bool direct)
+{
+ Render_Engine_GL_Generic *re = data;
+ Evas_GL_Image *im = image;
+
+ if (!im) return;
+ if (im->native.data && direct && re && re->func.get_pixels)
+ im->direct = EINA_TRUE;
+ else
+ im->direct = EINA_FALSE;
+}
+
//--------------------------------//
static int
// gl_current_context_get is in engine
ORD(gl_current_surface_get);
ORD(gl_rotation_angle_get);
+ ORD(gl_image_direct_get);
+ ORD(gl_image_direct_set);
ORD(image_load_error_get);