Multiple SDL windows with YUV Overlay - c

Does anyone know, how to create two Windows ans both should have an own YUV Overlay with the SDL 1.3 Library?
It is possible or do I try to use a wrong strategy?
If I tried the following source, i got an error message:
[!] can't create local overlay YUV display is only supported on the screen surface
#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
static bool running = true;
static SDL_Window* win_local;
static SDL_Window* win_remote;
int main(int argc, char** argv) {
// SDL_SetVideoMode
if((SDL_Init(SDL_INIT_VIDEO) != 0))
{
printf("[!] can't initialize SDL %s\n", SDL_GetError());
exit(-1);
}
if(!(win_local = SDL_CreateWindow("Local Video", 0, 0, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS)))
{
printf("[!] can't create Window %s\n", SDL_GetError());
exit(-1);
}
if(!(win_remote = SDL_CreateWindow("Remote Video", 700, 0, 640, 480, SDL_WINDOW_SHOWN)))
{
printf("[!] can't create Window %s\n", SDL_GetError());
exit(-1);
}
SDL_Surface* surface_local;
SDL_Surface* surface_remote;
if(!(surface_local = SDL_GetWindowSurface(win_local)))
{
printf("[!] can't get local surface %s\n", SDL_GetError());
exit(-1);
}
if(!(surface_remote = SDL_GetWindowSurface(win_remote)))
{
printf("[!] can't get remote surface %s", SDL_GetError());
exit(-1);
}
SDL_Overlay* overlay_local;
SDL_Overlay* overlay_remote;
if(!(overlay_local = SDL_CreateYUVOverlay(640, 480, SDL_IYUV_OVERLAY, surface_local)))
{
printf("[!] can't create local overlay %s\n", SDL_GetError());
exit(-1);
}
//
// if(!(overlay_remote = SDL_CreateYUVOverlay(640, 480, SDL_IYUV_OVERLAY, surface_remote)))
// {
// printf("[!] can't create remote overlay %s\n", SDL_GetError());
// exit(-1);
// }
SDL_Event event;
while(running)
{
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
running = false;
break;
case SDL_QUIT:
running = false;
break;
}
}
SDL_Delay(20);
}
//SDL_FreeSurface(local);
//SDL_FreeSurface(remote);
SDL_DestroyWindow(win_local);
SDL_DestroyWindow(win_remote);
SDL_Quit();
exit(0);
return 0;
}

SDL_CreateYUVOverlay doesn't work well with multiple windows, because it's not part of 1.3 API, it was left for reverse compatibility with SDL 1.2.
I see three possible solutions:
Call SDL_CreateYUVOverlay just after SDL_CreateWindow for each surface. You will probably avoid the error but I'm not sure if it will work correctly.
See how SDL_CreateYUVOverlay is implemented using 1.3 API and do something similar.
Use OpenGL and shaders.

Related

Window not displaying SDL2

I am using SDL2 for the first time, and when I try to create a window, it's not displaying. The only sight of the window is an icon spawning in my dock (Image of the icon, SDLTest.out is the name of my executable file). I found out that it spawned when SDL_INIT()was called.
I tried updating the window, changing its color and adding the flag SDL_WINDOW_SHOWN, but none of these solutions worked. I even pasted a code from the Internet, but it didn't work better.
Here is the code that I pasted:
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
int status = EXIT_FAILURE;
SDL_Color orange = {255, 127, 40, 255};
if(0 != SDL_Init(SDL_INIT_VIDEO))
{
fprintf(stderr, "Error SDL_Init : %s", SDL_GetError());
goto Quit;
}
window = SDL_CreateWindow("SDL2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480, SDL_WINDOW_SHOWN);
if(NULL == window)
{
fprintf(stderr, "Error SDL_CreateWindow : %s", SDL_GetError());
goto Quit;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(NULL == renderer)
{
fprintf(stderr, "Error SDL_CreateRenderer : %s", SDL_GetError());
goto Quit;
}
if(0 != SDL_SetRenderDrawColor(renderer, orange.r, orange.g, orange.b, orange.a))
{
fprintf(stderr, "Error SDL_SetRenderDrawColor : %s", SDL_GetError());
goto Quit;
}
if(0 != SDL_RenderClear(renderer))
{
fprintf(stderr, "Error SDL_SetRenderDrawColor : %s", SDL_GetError());
goto Quit;
}
SDL_Delay(500);
SDL_RenderPresent(renderer);
SDL_Delay(500);
status = EXIT_SUCCESS;
Quit:
if(NULL != renderer)
SDL_DestroyRenderer(renderer);
if(NULL != window)
SDL_DestroyWindow(window);
SDL_Quit();
return status;
}
My OS is MacOS 11.6, my compiler GCC, my computer has a graphic card Intel Iris Pro Graphics 6200, and I installed SDL2 using Homebrew.
Can someone help me?
I just needed an event loop. I added this code and it worked:
SDL_bool quit = SDL_FALSE;
while(!quit)
{
SDL_RenderPresent(renderer);
SDL_WaitEvent(&event);
if(event.type == SDL_QUIT)
quit = SDL_TRUE;
}
Thank you to HolyBlackCat for your comment!

SDL_SetColorKey() is not removing the background colour

I'm trying to set the transparency of my image. This code works fine in C++, but when I try the same code in C it no longer works. On executing the code, the image displays, however the black background remains. This is the code I'm using. Can anyone help me identify the issue?
SDL_Texture* Utilities_loadImage( SDL_Renderer* r, const char* file )
{
/* load an image into memory using SDL_image library function */
SDL_Surface* surface = SDL_LoadBMP(file);
if(!surface)
{
printf("error creating surface: %s\n", SDL_GetError());
return NULL;
}
if(SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0)) != 0)
{
printf("Unable to set colourkey: %s", SDL_GetError());
}
/* convert image into a texture for use by the grafx hardware */
SDL_Texture* texture = SDL_CreateTextureFromSurface(r, surface);
/* get rid of surface */
SDL_FreeSurface(surface);
if(!texture)
{
printf("error creating texture: %s\n", SDL_GetError());
return NULL;
}
return texture;
}
Well maybe in this specific line:
SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0))
you are calling the same variable "surface" and maybe the you background it's in other variable for example:
SDL_SetColorKey(background, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0))
and the variable surface it's the principal image that what you try to move or work.

"Couldn't find matching render driver!" from SDL_CreateRenderer()?

I came across this error when running my SDL program. It compiled just fine, but the window opened up for a brief moment then closed.
Here's my code:
//Using SDL and standard IO
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string.h>
// SDL Main Resources
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
SDL_Window* Window = NULL;
SDL_Texture* Canvas = NULL;
SDL_Renderer* Graphic_Renderer = NULL;
SDL_Event Event;
// Initialize SDL resources
int InitSDL_Environment(){
// Window
Window = SDL_CreateWindow("UML Prototype", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if(Window == NULL){
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
SDL_Quit();
return 0;
}
// Video Engine
if(SDL_Init(SDL_INIT_VIDEO) < 0){
printf( "SDL Video Engine could not be initialized! SDL Error: %s\n", SDL_GetError() );
return 0;
}
// Image Formats
int imgFlags = IMG_INIT_PNG;
if(!(IMG_Init(imgFlags) & imgFlags)){
printf("SDL Image Formats could not be initialized! SDL_image Error: %s\n", IMG_GetError());
return 0;
}
// Graphics Renderer
Graphic_Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
if(Graphic_Renderer == NULL){
printf("Graphics renderer could not be created! SDL Error: %s\n", SDL_GetError());
return 0;
}
SDL_SetRenderDrawColor(Graphic_Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
// Return Success
return 1;
}
// Load image from file
SDL_Texture* SDL_LoadTexture(char* src){
SDL_Texture* texture = NULL;
SDL_Surface* loadData = IMG_Load(src);
if(!loadData){
printf("Image \"%s\" could not be loaded! SDL_image ERROR: %s\n", src, IMG_GetError());
return NULL;
}
texture = SDL_CreateTextureFromSurface(Graphic_Renderer, loadData);
if(!texture){
printf("Image \"%s!\" could not be processed! SDL Error: %s\n", src, SDL_GetError());
}
SDL_FreeSurface(loadData);
return texture;
}
int main( int argc, char* args[] )
{
// Load SDL Resources
if(!InitSDL_Environment()){return 1;}
SDL_Texture* image = SDL_LoadTexture("Duck.png");
if(image == NULL){
printf("Image could not be found! SDL_Error: $s\n", SDL_GetError());
return 2;
}
SDL_Rect sign;
sign.x = 40;
sign.y = 31;
sign.w = 300;
sign.h = 300;
// Main loop
for(;;){
// Update screen
SDL_RenderClear(Graphic_Renderer);
SDL_RenderCopy(Graphic_Renderer, image, NULL, NULL);
SDL_RenderPresent(Graphic_Renderer);
// Event handling
SDL_PollEvent(&Event);
if(Event.type == SDL_QUIT){
SDL_DestroyWindow(Window);
SDL_Quit();
return 0;
}
}
}
When I adjusted the batch file to post program errors to the console window, it read Graphics renderer could not be created! SDL Error: Couldn't find matching render driver, pointing right to the Graphic_Renderer = SDL_CreateRenderer... line in my InitSDL_Environment() function.
As you can see, the first bit of that error is my own making, and the last bit was generated by SDL_GetError(), so it's an issue that SDL recognizes.
I found this forum post about the same basic issue where everyone suggested downloading OpenGL libraries. From there, I searched and found this link. No links on that page seemed to lead to anything I could download, and it became progressively ambiguous what OpenGL libraries to download, search for, or if it will even solve the issue. That forum post is four years old after all.
If it's an OpenGL problem with the SDL libraries, where exactly would I get the OpenGL libraries, and which ones should I download? Did I just do something dumb with my code?
So I did something dumb with my code! Of course <_<
I changed my InitSDL_Environment() function around, and it worked. I moved the SDL_CreateWindow function down below the SDL_Init(SDL_INIT_VIDEO) portion. So Initialize SDL Video, then create the window. Awesome!
// Initialize SDL resources
int InitSDL_Environment(){
// Video Engine
if(SDL_Init(SDL_INIT_VIDEO) < 0){
printf( "SDL Video Engine could not be initialized! SDL Error: %s\n", SDL_GetError() );
return 0;
}
// Image Formats
int imgFlags = IMG_INIT_PNG;
if(!(IMG_Init(imgFlags) & imgFlags)){
printf("SDL Image Formats could not be initialized! SDL_image Error: %s\n", IMG_GetError());
return 0;
}
// Window
Window = SDL_CreateWindow("UML Prototype", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if(Window == NULL){
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
SDL_Quit();
return 0;
}
// Graphics Renderer
Graphic_Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
if(Graphic_Renderer == NULL){
printf("Graphics renderer could not be created! SDL Error: %s\n", SDL_GetError());
return 0;
}
SDL_SetRenderDrawColor(Graphic_Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
// Return Success
return 1;
}
The comments brought up three main points:
SDL Textures require computers to have a graphics card & up-to-date drivers for them, which may need to be updated manually.
SDL Video needs to be initialized before a window can be created
The functions SDL_GetNumRenderDrivers() and SDL_GetRendererInfo() can be used to find out information about available cards and trouble-shoot this error.
Thanks commentators! This was a huge help.

X11/Xlib/xcb: Creating a window requires border pixel if specifying colormap. Why?

When creating an X window using either Xlib or xcb, I have found that I must provide the border pixel attribute if I want to provide a colormap. This requirement seems strange to me as I'm note sure how these two attributes relate and I wondered if anyone could share some insight as to why this is the case.
The two examples below create an X window with a depth of 32 and a True Color visual class. In both examples, if the mask for the color map is removed along with the corresponding value, I get unexpected behaviour in the program.
In xcb I get a BadMatch error when the cookie is checked, whereas in the Xlib example the window creates successfully but is not mapped.
Can someone explain why neither Xlib or xcb work without specifying the Border Pixel attribute and also why each library manifests the error in different ways?
Xlib.c:
int main()
{
Display *display = XOpenDisplay(NULL);
if (!display) {
/* TODO(djr): Logging */
fputs("X11: Unable to create connection to display server", stderr);
return -1;
}
int screen = DefaultScreen(display);
Window root = RootWindow(display, screen);
XVisualInfo vinfo = {0};
if (!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
/* TODO(djr): Logging */
fputs("X11: Unable to find supported visual info", stderr);
return -1;
}
Colormap colormap = XCreateColormap(
display, root, vinfo.visual, AllocNone);
const unsigned long wamask = CWColormap | CWBorderPixel;
XSetWindowAttributes wa;
wa.colormap = colormap;
wa.border_pixel = WhitePixel(display, screen);
Window window = XCreateWindow(
display,
root,
0, 0,
1600, 900,
1, /* border width */
vinfo.depth,
InputOutput,
vinfo.visual,
wamask,
&wa);
if (!window) {
/* TODO(djr): Logging */
fputs("X11: Unable to create window", stderr);
return -1;
}
XMapWindow(display, window);
XFlush(display);
pause();
XCloseDisplay(display);
return 0;
}
xcb.c:
int main()
{
xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
fprintf(stderr, "ERROR: failed to connection to X server\n");
return -1;
}
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_t *screen = xcb_setup_roots_iterator(setup).data;
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen);
xcb_depth_t *depth = NULL;
while (depth_iter.rem) {
if (depth_iter.data->depth == 32 && depth_iter.data->visuals_len) {
depth = depth_iter.data;
break;
}
xcb_depth_next(&depth_iter);
}
if (!depth) {
fprintf(stderr, "ERROR: screen does not support 32 bit color depth\n");
xcb_disconnect(connection);
return -1;
}
xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth);
xcb_visualtype_t *visual = NULL;
while (visual_iter.rem) {
if (visual_iter.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) {
visual = visual_iter.data;
break;
}
xcb_visualtype_next(&visual_iter);
}
if (!visual) {
fprintf(stderr, "ERROR: screen does not support True Color\n");
xcb_disconnect(connection);
return -1;
}
xcb_colormap_t colormap = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_colormap_checked(
connection,
XCB_COLORMAP_ALLOC_NONE,
colormap,
screen->root,
visual->visual_id);
xcb_generic_error_t *error = xcb_request_check(connection, cookie);
if (error) {
fprintf(stderr, "ERROR: failed to create colormap: %s\n", xcb_errors[error->error_code]);
xcb_disconnect(connection);
return -1;
}
unsigned int cw_mask = XCB_CW_COLORMAP | XCB_CW_BORDER_PIXEL;
unsigned int cw_values[] = { screen->white_pixel, colormap };
xcb_window_t window = xcb_generate_id(connection);
cookie = xcb_create_window_checked(
connection,
depth->depth,
window,
screen->root,
0, 0,
1600, 900,
1,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id,
cw_mask,
cw_values);
error = xcb_request_check(connection, cookie);
if (error) {
fprintf(stderr, "ERROR: failed to create window: %s\n", xcb_errors[error->error_code]);
xcb_disconnect(connection);
return -1;
}
xcb_map_window(connection, window);
xcb_flush(connection);
pause();
xcb_disconnect(connection);
return 0;
}
I just tried your program and it fails even if I don't specify the colormap, so I think that the colormap is unrelated to your problem.
I'm not totally sure, but my guess is that the default border pixmap is XCB_COPY_FROM_PARENT, and that must match the window visual and depth. But you are setting the visual and depth (different than those of the parent). Now, the border visual or depth is different than that of the window, so you get a BadMatch.
By specifying a border pixel color, X creates a pixmap of appropriate attributes and sets it as the border pixmap and everything works again.

SDL2 - Crash when trying to copy surface information to structure. No error message given

#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
typedef struct{
SDL_Texture *texture; // The image/sprite itself
int width; // Sprite width
int height; // Sprite height
} Sprite;
Sprite *createSprite(SDL_Renderer *r, char *path);
int main(int argc, char *argv[]){
// Initialise SDL and SDL_image
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
// Create window
SDL_Window *window = SDL_CreateWindow(
"VN", // Title
SDL_WINDOWPOS_CENTERED, // Initial x position
SDL_WINDOWPOS_CENTERED, // Initial y position
1280, // Width
720, // Height
0 // Flags
);
if(window == NULL){
printf("Failed to create window. %s\n", SDL_GetError());
return 1;
}
// Create renderer
SDL_Renderer *renderer = SDL_CreateRenderer(
window, // Window
-1, // Monitor index (-1 for first available)
SDL_RENDERER_ACCELERATED // Flags
);
if(renderer == NULL){
printf("Failed to create renderer. %s\n", SDL_GetError());
return 1;
}
// Set up event handling
SDL_Event event;
while(1){
// Handle events/input
while(SDL_PollEvent(&event) != 0){
// Check if user wants to quit (press window close button)
if(event.type == SDL_QUIT){
return 1;
}
}
// Set screen colour to white
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
// Render white to screen (clear screen)
SDL_RenderClear(renderer);
// Update screen
SDL_RenderPresent(renderer);
}
// Exit SDL and SDL_image
SDL_Quit();
IMG_Quit();
return 0;
}
Sprite *createSprite(SDL_Renderer *r, char *path){
printf("Entered createSprite()\n");
// Create a Sprite structure, containing an image (texture) and its dimensions
Sprite *newSprite = NULL;
SDL_Texture *spriteTexture = NULL;
// Temporary surface (for loading texture)
SDL_Surface *tempSurface = NULL;
// Load image from path
tempSurface = IMG_Load(path);
if(tempSurface == NULL){
printf("Failed to load image '%s'. %s\n", path, IMG_GetError());
} else{
spriteTexture = SDL_CreateTextureFromSurface(r, tempSurface);
if(spriteTexture == NULL){
printf("Failed to create texture from '%s'. %s\n", path, SDL_GetError());
} else{
// Store texture, image width & height in Sprite structure
newSprite->texture = spriteTexture;
newSprite->width = tempSurface->w;
newSprite->height = tempSurface->h;
}
}
// Free memory of temp surface
SDL_FreeSurface(tempSurface);
printf("Leaving createSprite()\n");
return newSprite;
}
I'm attempting to load an image using the SDL_image addon, and store its width and height in a structure (along with a texture created from the surface).
It crashes when attempting to run the newSprite->texture = spriteTexture; section on Line 93. That's as much information as I can give I'm afraid. Any ideas?
I'm attempting to load an image using the SDL_image addon, and store its width and height in a structure (along with a texture created from the surface).
The problem is you're not allocating memory for Sprite in your createSprite function. You set it to NULL and than try to access that location which of course fails.
Try this:
Sprite *createSprite(SDL_Renderer *r, char *path){
printf("Entered createSprite()\n");
// Create a Sprite structure, containing an image (texture) and its dimensions
Sprite *newSprite = new Sprite(); //<<- this is where you allocate the memory
SDL_Texture *spriteTexture = NULL;
// Temporary surface (for loading texture)
SDL_Surface *tempSurface = NULL;
// Load image from path
tempSurface = IMG_Load(path);
if(tempSurface == NULL){
printf("Failed to load image '%s'. %s\n", path, IMG_GetError());
} else{
spriteTexture = SDL_CreateTextureFromSurface(r, tempSurface);
if(spriteTexture == NULL){
printf("Failed to create texture from '%s'. %s\n", path, SDL_GetError());
} else{
// Store texture, image width & height in Sprite structure
newSprite->texture = spriteTexture;
newSprite->width = tempSurface->w;
newSprite->height = tempSurface->h;
}
}
// Free memory of temp surface
SDL_FreeSurface(tempSurface);
printf("Leaving createSprite()\n");
return newSprite;
}

Resources