[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [E-devel] Buffer canvas and transparent background



On Sun, 2006-04-02 at 15:18 +0000, jose_ogp@juno.com wrote:
> 	In your example, you have an output size of (640, 480), and
> a viewport at (0,0) of size (800, 600).
> 	You then create a rectangle object of *canvas* coordinate
> size (700, 50) and move it to the *canvas* position (0, 300).

I understand that.  My test case wasn't meant to demonstrate best
practices. :)


> 	This means that in *output* coordinates, your rectangle will
> be of *output* size (560, 40) and its top-left at *output* position
> (0, 240).
> 	At the output position of (0, 300) there is NO rectangle since
> your rectangle begins at output y-pos of y = 240, and ends at output
> y-pos of y = (240 + 40).

That is why I sampled in the buffer at y=250.  The code was correct.  It
wasn't pretty, but it was correct, and demonstrated my point, I hope. :)


> 	As Carsten mentioned, evas won't 'zero' the canvas by default.
> 	Thus, since you did not specify any values for the canvas as
> a whole, the color at x = 0, y = 300, will be junk.
> 	Moving the rectangle to (0,0) will still not give anything
> meaningful at (0,300) since nothing was ever drawn there, and thus
> nothing was cleared there.

It has always worked in the past that evas will zero the alpha of the
areas I move objects away from for at least the buffer engine.  This
behaviour is quite necessary for us because we use evas to render an
OSD.  

And indeed, if I use ABGR32, this is what happens.  raster explained
this ABGR32 does zero out the alpha for those regions that were rendered
to but this doesn't seem to also happen for BGR32.

In any case, would the correct way to ensure this be to create a
rectangle the full size of the canvas and set its color to (0, 0, 0, 0)?
Well perhaps not; I just tried this and the results are the same.

See the attached example, refined to include the (0,0,0,0) rectangle for
background and a call to evas_coord_world_y_to_screen() just to convince
you I really am testing in the right location in the buffer :)

When using ABGR32 canvas or either ABGR32/BGRA32 from cvs-2005-12-18
(which isn't any significant date; just happens to be my last cvs
checkout), I get the results I expect:

        Before move: 120,110,100,130
        Update: 0,0 560x40
        Update: 0,240 560x40
        After move: 120,110,100,0

Using BGR32 canvas from cvs-2006-04-01 (or 0.9.9.026):

        Before move: 61,56,51,66
        Update: 0,0 560x40
        Update: 0,240 560x40
        After move: 61,56,51,66

Note the alpha is still 66 after the move.  The pixel values here seem
all wonky too.  I commented about this in my last email.

However, if I change the viewport size to match output size:

        Before move: 61,56,51,66
        Update: 0,0 640x56
        Update: 0,296 640x56
        After move: 0,0,0,0

Pixel values still wrong, but at least now it's zeroing the alpha at the
old location after object move.

So there seems to be two separate problems with BGRA32 here.

Cheers!
Jason.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <Evas.h>
#include <Evas_Engine_Buffer.h>

int main(int argc, char **argv)
{
    unsigned char *buffer = malloc(640*480*4);
    Evas_Engine_Info_Buffer *einfo;

    evas_init();
    Evas *evas = evas_new();

    evas_output_method_set(evas, evas_render_method_lookup("buffer"));
    einfo = (Evas_Engine_Info_Buffer *) evas_engine_info_get(evas);
    // Change this to EVAS_ENGINE_BUFFER_DEPTH_ARGB32 and everything works.
    einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_BGRA32;
    einfo->info.dest_buffer_row_bytes = 640*4;
    einfo->info.dest_buffer = buffer;

    evas_engine_info_set(evas, (Evas_Engine_Info *) einfo);

    evas_output_size_set(evas, 640, 480);

    evas_output_viewport_set(evas, 0, 0, 800, 600);
    // NOTE: uncomment this line and alpha is zeroed after move.
    //evas_output_viewport_set(evas, 0, 0, 640, 480);
    
    Evas_Object *bg = evas_object_rectangle_add(evas);
    evas_object_color_set(bg, 0, 0, 0, 0);
    evas_object_resize(bg, 800, 600);
    evas_object_move(bg, 0, 0);
    evas_object_show(bg);

    Evas_Object *rect = evas_object_rectangle_add(evas);
    evas_object_color_set(rect, 100, 110, 120, 130);
    evas_object_resize(rect, 700, 50);
    evas_object_move(rect, 0, 300);
    evas_object_show(rect);

    evas_render(evas);
    int offset = 640*4*evas_coord_world_y_to_screen(evas, 310);

    printf("Before move: %d,%d,%d,%d\n", buffer[offset], buffer[offset+1], buffer[offset+2], buffer[offset+3]);

    evas_object_move(rect, 0, 0);
    Evas_List *u;
    for (u = evas_render_updates(evas); u; u = u->next) {
        Evas_Rectangle *r = u->data;
        printf("Update: %d,%d %dx%d\n", r->x, r->y, r->w, r->h);
    }

    printf("After move: %d,%d,%d,%d\n", buffer[offset], buffer[offset+1], buffer[offset+2], buffer[offset+3]);
}