The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Raspberry pi Alpha transparency
McNemisis


Joined: 01 Mar 2015
Posts: 6
Hi All,
I've been working on this for a few days now and not getting any closer to a result.

i'm trying to use sdl to make a overlay type display on top of the raspberry pi camera.
however no matter what i try i can't seem to get it to work i always end up with a black background that is over writing the display under it.

i know it can be done as I've got a proto type mocked up using the dispman hello font example.

the code i'm trying is
Code:

#include <stdio.h>
#include "SDL.h"
#include "SDL_image.h"

int main(int argc, char **argv)
{
   if (SDL_Init(SDL_INIT_VIDEO) !=0) {
      printf("Error SDL_Init %s \n",SDL_GetError());
   }
   SDL_Window *window;
   window = SDL_CreateWindow(
      "Test",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED,
      640,
      480,
      SDL_WINDOW_OPENGL
      );
   if (window == NULL) {
      printf("Error with Window %s \n",SDL_GetError());
   }
   SDL_Renderer *ren;
   ren = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED |
      SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
   
   SDL_Texture *tex;
   tex = SDL_CreateTexture(ren,SDL_PIXELFORMAT_ARGB8888,
      SDL_TEXTUREACCESS_TARGET,500,500);
   if (tex == NULL) {
      printf("textur error %s \n",SDL_GetError());
   }
   SDL_SetTextureBlendMode(tex,SDL_BLENDMODE_BLEND);
   
   SDL_SetRenderTarget(ren,tex);
   SDL_SetRenderDrawColor(ren,0,0,0,0);
   SDL_RenderClear(ren);
   SDL_SetRenderTarget(ren,NULL);
   SDL_Rect rect;
      rect.x=0;
      rect.y=0;
      rect.h=300;
      rect.w=300;
   
   SDL_SetRenderDrawColor(ren,255,255,255,255);
   SDL_RenderFillRect(ren,&rect);   
   
   SDL_RenderPresent(ren);
   SDL_Delay(3000);
   return 0;
}


the only way i've been able to get close is to modify the following in the source code.

Code:
 /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */
    dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
    dispman_alpha.opacity = 100;
    dispman_alpha.mask = 0;

this works but makes the entire window transparent including anything i draw onto it.

i'm using arch Linux with a PKGBUILD version of sdl that disables opengl and makes SDL2 use the dispmanx backend.

can anyone point me in the right direction with this???

Thanks
Matthew
camperman


Joined: 09 Apr 2015
Posts: 4
You're almost there Smile

There's two fixes you need to apply to get SDL to overlay transparently. One is there in the source you pasted:

Code:
dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;


Change this to:

Code:
dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE;


This tells dispmanx to pick up the source alpha from your drawing. If you fill the area with alpha=0, it will be totally transparent. If with 255, totally opaque - and so on.

The other fix is to do with the video memory layering in the Pi. Larger numbered layers obscure lower numbered ones, starting at 1 (I think). SDL's is defined to be 10000 in src/video/raspberry/SDL_rpivideo.h:

Code:
#define SDL_RPI_VIDEOLAYER 10000 /* High enough so to occlude everything */


I've changed it to 10 so I can redirect video from omxplayer both above and below it. You may not need this. I don't know what video layer the camera uses but if you create a completely transparent surface that's above the camera layer and then draw opaque elements to it, they will display correctly.
McNemisis


Joined: 01 Mar 2015
Posts: 6
Cool, i'm gonna see if i can try this now and will report back.

out of interest as i understand it the Raspberry pi has 3 layers do you know why it's been set to 1000 or 10 for example instead of just 0-2

Thanks
Matthew
camperman


Joined: 09 Apr 2015
Posts: 4
dispmanx can cope with up to 64 elements before it breaks from lack of video ram or video bandwidth (in my experience anyway - there's no useful docs on this). You can number those arbitrarily from 0 upwards so that a higher number obscures a lower one. I don't think there's any numbering built into the hardware as such. I've experimented with one video playing on layer 3, one on layer 5 (both in windows), transparent overlays on layer 10, and another video on layer 20. dispmanx just orders these from top to bottom and they all work correctly. omxplayer includes a --layer option to direct video onto a layer you provide - does the camera software do the same thing?
McNemisis


Joined: 01 Mar 2015
Posts: 6
it does yes,
I'm using code from the Raspberry pi's video record program seemed silly to rewrite the hole thing again.
you can change the layer of the preview window in source but not from the cmdline.

regarding the layer numbering I had it the wrong way I though the 64 elements limit was to-do with the number of objects on the screen not the number of layers on the screen.
is that right?

Thanks
Matthew
McNemisis


Joined: 01 Mar 2015
Posts: 6
I've made the change and it's not made a difference although i'm sure it needs to be there for it to work.

i've done some tests and can get a renderer to display under the camera by setting the camera preview layer to 30 and the sdl2 layer to 10.

i also tried removing the following lines
Code:
 
dispman_alpha.opacity = 0xFF;
dispman_alpha.mask = 0;


and again no difference,

this is the relevant SDL section for the test I'm running,
i should get a semi transparent colour across the screen.

Code:

   if (SDL_Init(SDL_INIT_VIDEO) !=0) {
      printf("Error SDL_Init %s \n",SDL_GetError());
   }
   printf("Before Window %s \n",SDL_GetError());
   SDL_Window *window;
   window = SDL_CreateWindow(
      "Test",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED,
      640,
      480,
      SDL_WINDOW_OPENGL
      );
      
   if (window == NULL) {
      printf("Error with Window %s \n",SDL_GetError());
   }
   SDL_GLContext context;
   context = SDL_GL_CreateContext(window);
   glClearColor(0.0f,1.0f,0.0f,0.50f);
   glFlush();
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
   printf("After Window %s \n",SDL_GetError());

   SDL_Renderer *ren;
   ren = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED |
      SDL_RENDERER_PRESENTVSYNC);
   if (ren == NULL) {
      printf("Render error %s \n",SDL_GetError());
   }
   
   SDL_Rect rect;
      rect.x=0;
      rect.y=0;
      rect.h=300;
      rect.w=300;
   SDL_SetRenderDrawBlendMode(ren,SDL_BLENDMODE_BLEND);
   SDL_SetRenderDrawColor(ren,255,255,255,255);
   SDL_RenderFillRect(ren,&rect);   
   printf("ERR Check %s \n",SDL_GetError());
   char *me;
   SDL_GetWindowData(window,"test");
   printf("SDL Window Data %s \n",&me);   
   
   SDL_GL_SwapWindow(window);
   //SDL_RenderPresent(ren);

it's messy but I'm still in the testing stage.

is it possible that I've messed up the linking some how and it's using the mesa gl instead of raspberry pi's built in.

Many Thanks
Matthew
camperman


Joined: 09 Apr 2015
Posts: 4
Sorry, you're quite right - it's elements. My elements are almost always full screen windows which is why I got confused Smile
McNemisis


Joined: 01 Mar 2015
Posts: 6
No worries I just wanted to much sure I understood it correctly.
camperman


Joined: 09 Apr 2015
Posts: 4
I don't see why your code doesn't work Confused Double-check the linking, yeah.
Raspberry pi Alpha transparency
McNemisis


Joined: 01 Mar 2015
Posts: 6
Hi All, I've been working on this for a few days now and not getting any closer to a result. i'm trying to use sdl to make a overlay type display on top of the raspberry pi camera. however no matter what i try i can't seem to get it to work i always end up with a black background that is over writing the display under it. i know it can be done as I've got a proto type mocked up using the dispman hello font example. the code i'm trying is Code: #include #include "SDL.h" #include "SDL_image.h" int main(int argc, char **argv) { if (SDL_Init(SDL_INIT_VIDEO) !=0) { printf("Error SDL_Init %s \n",SDL_GetError()); } SDL_Window *window; window = SDL_CreateWindow( "Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL ); if (window == NULL) { printf("Error with Window %s \n",SDL_GetError()); } SDL_Renderer *ren; ren = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); SDL_Texture *tex; tex = SDL_CreateTexture(ren,SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,500,500); if (tex == NULL) { printf("textur error %s \n",SDL_GetError()); } SDL_SetTextureBlendMode(tex,SDL_BLENDMODE_BLEND); SDL_SetRenderTarget(ren,tex); SDL_SetRenderDrawColor(ren,0,0,0,0); SDL_RenderClear(ren); SDL_SetRenderTarget(ren,NULL); SDL_Rect rect; rect.x=0; rect.y=0; rect.h=300; rect.w=300; SDL_SetRenderDrawColor(ren,255,255,255,255); SDL_RenderFillRect(ren,&rect); SDL_RenderPresent(ren); SDL_Delay(3000); return 0; }
the only way i've been able to get close is to modify the following in the source code. Code: /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; dispman_alpha.opacity = 100; dispman_alpha.mask = 0;
this works but makes the entire window transparent including anything i draw onto it. i'm using arch Linux with a PKGBUILD version of sdl that disables opengl and makes SDL2 use the dispmanx backend. can anyone point me in the right direction with this??? Thanks Matthew