How do you create a transparent window using dispmanx on Raspberry Pi? - sdl

I'm working on a slideshow app and using SDL 1.2 using a custom dispmanx backend (https://github.com/vanfanel/SDL12-kms-dispmanx) with Pygame to create overlays on top of omxplayer.
It all works well and layers correctly, but I can't seem to make a transparent canvas in dispmanx without making my objects transparent as well. My understanding is Pygame itself cannot handle this and it is up to SDL to handle transparency between dispmanx layers.
My goal is a hardware accelerated transparent canvas the size of my screen above omxplayer that I can draw on.
I suspect there must be a method other than using the alpha settings in vc_dispmanx_element_add to do this? XBMC uses dispmanx and can do opaque overlays above omxplayer, so this must be possible. I've also looked at vc_dispmanx_display_set_background, but this seems to only take RGB and not an alpha.

Rather than creating a transparent window u could take a screenshot of the window and use it as a background. To do this i used pyscreenshot to take the image (though there are other options) and
os.environ['SDL_VIDEO_WINDOW_POS']="0,0"
to make sure the window is in the right spot every time, the only weakness to this is that the window is no longer transparent if something changes behind it

Check out my library built for exactly this use case: https://github.com/dtcooper/python-dispmanx
You can use pygame as follows,
from random import randint
import pygame
from dispmanx import DispmanX
# Generate a random color with alpha compontent
def random_color_with_alpha():
return tuple(randint(0, 0xFF) for _ in range(3)) + (randint(0x44, 0xFF),)
display = DispmanX(pixel_format="RGBA")
surface = pygame.image.frombuffer(
display.buffer, display.size, display.pixel_format
)
clock = pygame.time.Clock()
for _ in range(20):
surface.fill(random_color_with_alpha())
display.update()
clock.tick(2)
Alternately, there's an another C Python extension that I didn't write that also functions the same way: https://github.com/eclispe/pyDispmanx

Related

Set an image as a background for a DrawingArea

I'm doing a platformer game using gtkmm and cairo, and i can't find a way to set an image as a background, so i don't have to redraw it on every draw event. I'm managing images as pixbufs.
Is it actually possible, or am i thinking it wrong?
Redraw events are always necessary. The difference is about who has to take care of them. Lower level libraries such as Cairo require you to do that.
Maybe you should look into Goocanvas. Particularly for games where you have to move things around easily and capture events, a higher level library than Cairo is handy. GooCanvas also handles screen redraws.
You can just put in the image with GooCanvasImage, and forget about it.
If you're not bound to C++, then have a look at PyGame for Python - it not only handles those events, but provides loads of other tools for game programming.

Creating a window in pygame without displaying it

I create a screen in pygame using:
screen = pygame.display.set_mode((width,height))
Then I draw 200 random gray scale circles on it and save the screen as an image. (I need to save this screen as an image so I can compare it to a target image later on):
pygame.image.save(screen, "Circles.png")
Now, I need to randomly change different parameters of different circles by putting the numpy array that contains the circle parameters for all the circles in a loop with a big number as its iteration value.
And I need to redraw the mutated circles on a screen (at the end of each iteration) and save that screen as a png image again.
Now the problem is, every time I use pygame.display.set_mode((width,height)) it opens up the display window and it significantly slows down my program.
I would like to create a screen and save it in a variable but don't need to display that screen at each iteration. I haven't been able to figure out what command to use to avoid displaying the screen.
I appreciate your help.
If you don't want a window to appear, try creating the surface like this:
screen = pygame.Surface((width,height))
Then you can draw your circles on this surface and save it the same way as you did before. As others have said, clear the surface with the fill() method.
I would probably end up using something like this. This will still popup a screen but it will be tiny and never updated.
import pygame
from pygame.locals import *
pygame.init()
def circle_drawing(surf):
pass
#your circle drawing function using passed in surface
DISPLAY = (1, 1)
DEPTH = 32
FLAGS = 0
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
work_surface = pygame.Surface((500,500))
count = 0
while True:
ws = circle_drawing(work_surface.copy())
pygame.image.save(ws, "circles_" + str(count)+".png")
count +=1

How to get X to render to an OpenGL texture?

I am trying to write a compositor, like Compiz, but with different graphical effects. I am stuck at the first step, though, which is that I can't find how to get X to render windows to a texture instead of to the framebuffer. Any advice on where to start?
X11 composition goes like following.
you redirect windows into a offscreen area. The Composite extension has the functions for this
you use the Damage extension to find out which windows did change their contents
in the compositor you use the GLX_EXT_texture_from_pixmap extension to submit each windows' contents into corresponding OpenGL textures.
you draw the textures into a composition layer window; the Composite extension provides you with a special screen layer, between the regular window layer and the screensaver layer in which to create the window composition is taking place in.

Creating a program that creates a full screen overlay

I want to write a program that would create a transparent overlay filling the entire screen in Windows 7, preferably with C++ and OpenGL. Though, if there is an API written in another language that makes this super easy, I would be more than willing to use that too. In general, I assume I would have to be able to read the pixels that are already on the screen somehow.
Using the same method screen capture software uses to get the pixels from the screen and then redrawing them would work initially, but the problem would then be if the screen updates. My program would then have to minimize/close and reappear in order for me to be able to read the underlying pixels.
Windows Vista introduced a new flag into the PIXELFORMATDESCRIPTOR: PFD_SUPPORT_COMPOSITION. If the OpenGL context is created with an alpha channel, i.e. AlphaBits of the PFD is nonzero, the alpha channel of the OpenGL framebuffer is respected by the Windows compositor.
Then by creating a full screen, borderless, undecorated window you get this exakt kind of overlay you desire. However this window will still receive all input events, so you'll have to do some grunt work and pass on all input events to the underlying windows manually.

Questions about OpenGL Settings and drawing over a mask in a window

I would like to know the OpenGL Rendering settings for having a program render OpenGL over top of any window on screen that has a specific color code (screen-level buffer?)
I.E. VLC Media Player and Media Player Classic both have rendering modes which allow you to full-screen then minimize player, but maintain watching media via allowing a specific color to act as a transparent mask. For example, you could set the background color of a terminal application to be 0x000010 for VLC 0x000001 for MPC and you could then type over the media using text (as it is in it's original color). When you try to do a "printscreen" all you get is the mask color, However, this is an acceptable side-effect.
Is it possible to do this as well with any OpenGL application with the right settings and hardware? If so, what are the settings or at least the terminology of this effect to further research it?
What you are trying to implement is called "overlay". You can try this angelcode tutorial. If I remember correctly, there was also a tutorial in DirectX SDK.
If you need to use OpenGL, you will need to perform offscreen rendering (using FBO or P-buffer), read the results using glReadPixels() and display using overlay.