Can't run SDL(2) on Ubuntu, No available video device - c

When i try to run my program i get the following error message:
SDL could not initialize! SDL_Error: No available video device
I have all the necessary SDL libraries installed and I'm currently running ubuntu 15.10
Here is my simple SDL code:
#include <stdio.h>
#include "SDL2/SDL.h"
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main(int argc, char* argv[])
{
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
//Create window
window = SDL_CreateWindow("SDL Tutorial",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());
}
}
return 0;
}
The SDL2 library are correctly linked to my C project.

This error message occurs when there is no available video driver built into SDL2 for your display system (X11, Mir, Wayland, RPI ...).
Have you installed SDL2 package from Ubuntu repository or compiled from source ? When compiled from source, you should check that the supported video drivers are going to be built into the binary at the end of the "configure" step. Otherwise you need to install the required development headers (for X11 and Mir).

Related

C SDL2 Error: No hardware accelerated renderers available

I'm trying to create a pong game with sdl2 in c. I'm able to make it work in a laptop running UBUNTU 20.04 (gtx 1650 mobile) with nvidia driver 470. But running it on the same setup in ubuntu 21.10 with nvidia 470 on a different laptop (rtx 3060 mobile) gives me this error.
Here's the code (stripped off any game logic to only part where it crashes).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include "SDL2/SDL.h"
const int SCREEN_WIDTH = 1200;
const int SCREEN_HEIGHT = 800;
int main(int argc, char** argv)
{
int sdl_init_status = SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER);
if (sdl_init_status != 0)
{
printf("Initialization failed. Error: %s \n", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow("PONG", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_RESIZABLE);
if (!window)
{
printf("Window initialization error: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
puts("Window created");
// // create renderer
Uint32 rflags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, rflags);
if (!renderer)
{
printf("renderer initialization error: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
puts("Renderer created");
SDL_Surface* screen_surface = SDL_GetWindowSurface(window);
if (!screen_surface)
{
printf("surface initialization error: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
puts("Surface created");
SDL_Delay(1000);
// cleanup and quit
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
This is the output I get:
gcc -std=c99 -g3 -Wall -o1 -o main main.c `sdl2-config --libs --cflags` -lm -lSDL2_image
./main
Window created
Renderer created
surface initialization error: No hardware accelerated renderers available
make: *** [Makefile:10: test] Error 1
You have
Uint32 rflags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, rflags);
Your error states No hardware accelerated renderers available.
The documentation for SDL_CreateRenderer refers 4 flags you can use.
I was having this issue on Android devices and solved with replacing the flags in SDL_CreateRenderer with only SDL_RENDERER_SOFTWARE. So use
Uint32 rflags = SDL_RENDERER_SOFTWARE;
instead.

"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.

Why egl pixmap surface works with opengl es but not with opengl?

I use EGL with Xlib and OpenGL. While I was drawing straight on the window everything was fine. Now I'm trying to use pixmaps as EGL surface but OpenGL doesn't change it at all.
I clean the background with the blue color using OpenGL. Here's what I get instead:
Here's minimal example demonstaiting the problem(drawing this trash).
UPDATE: I added error checks and find out that eglCopyBuffers produces EGL_BAD_NATIVE_PIXMAP. Docs tell this can happen in two cases: if implementation doesn't support native pixmaps or if native pixmap argument is not valid. They both seem unlikely. If I can create pixmap surface without error I believe implementation supports native pixmaps. if I can draw on the pixmap using native methods like XFillRectangle I believe pixmap is valid.
UPDATE: I'm running this on a laptop with Ubuntu Gnome. It has two video cards: Intel HD Graphics 5500(driver=i915) and Nvidia GeForce 920m(driver=nvidia). Main lines from es2_info output(full version):
EGL_VERSION: 1.4
EGL_VENDOR: NVIDIA
EGL_CLIENT_APIS: OpenGL_ES OpenGL
GL_VERSION: OpenGL ES 3.2 NVIDIA 375.66
GL_RENDERER: GeForce 920M/PCIe/SSE2
Code:
// main.c
// cc main.c -lX11 -lEGL -lGL
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <EGL/egl.h>
#include <X11/Xlib.h>
void
die(const char * errstr, ...) {
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(1);
}
int main() {
Display * display = XOpenDisplay(NULL);
if (!display) die("Can't create xlib display.\n");
int screen = XDefaultScreen(display);
GC gc = XDefaultGC(display, screen);
Window root_window = XRootWindow(display, screen);
unsigned long black_pixel = XBlackPixel(display, screen);
unsigned long white_pixel = XWhitePixel(display, screen);
Window window = XCreateSimpleWindow(display, root_window, 0, 0, 640, 480,
0, black_pixel, white_pixel);
if (!window) die("Can't create window.\n");
int res = XSelectInput(display, window, ExposureMask);
if (!res) die("XSelectInput failed.\n");
Pixmap pixmap = XCreatePixmap(display, window, 400, 400, 24);
if (!pixmap) die("Can't create pixmap.\n");
EGLDisplay egldisplay = eglGetDisplay(display);
if (EGL_NO_DISPLAY == egldisplay) die("Can't cate egl display.\n");
res = eglInitialize(egldisplay, NULL, NULL);
if (!res) die("eglInitialize failed.\n");
EGLConfig config;
int num_configs;
static int attrib_list[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 0,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
EGL_NONE
};
res = eglChooseConfig(egldisplay, attrib_list, &config, 1, &num_configs);
if (!res) die("eglChooseConfig failed.\n");
if (0 == num_configs) die("No appropriate egl config found.\n");
EGLSurface surface =
eglCreatePixmapSurface(egldisplay, config, pixmap, NULL);
if (EGL_NO_SURFACE == surface) die("Can't create egl pixmap surface.\n");
res = eglBindAPI(EGL_OPENGL_API);
if (!res) die("eglBindApi failed.\n");
EGLContext context =
eglCreateContext(egldisplay, config, EGL_NO_CONTEXT, NULL);
if (EGL_NO_CONTEXT == config) die("Can't create egl context.\n");
res = eglMakeCurrent(egldisplay, surface, surface, context);
if (!res) die("eglMakeCurrent failed.\n");
res = XMapWindow(display, window);
if (!res) die("XMapWindow failed.\n");
while (1) {
XEvent event;
res = XNextEvent(display, &event);
if (Expose != event.type) continue;
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glFinish();
res = eglWaitGL();
if (!res) die("eglWaitGL failed.\n");
res = XCopyArea(display, pixmap, window, gc, 0, 0, 400, 400, 0, 0);
if (!res) die("XCopyArea failed.\n");
}
}
Turns out eglBindApi(EGL_OPENGL_API) is source of the issue. When you delete one you get blue square as expected.
By default EGL uses OpenGL ES as rendering API and It simply doesn't work with OpenGL rendering API . I couldn't find single example of code that uses EGL with OpenGL rendering API but I found this answer. This makes me think EGL isn't supposed to work with OpenGL even though eglBindApi(EGL_OPENGL_API) doesn't return EGL_BAD_PARAMETER which must be returned accroding to docs "if the specified client API is not supported by the EGL implementation".
So I don't accept this as an answer because actual reason why setting OpenGL as rendering API breaks the code is still unknown.

SDL2 Window lacking window bar

I'm trying to build an SDL2 app on OSX El Capitan, and I am running into an issue where the window dressing is not appearing. Things like the exit button and the resizing bar are not appearing. I've compiled on Windows and it all works fine there.
To make it a bit easier this link to Lazy Foo's tutorial replicates the issue: http://lazyfoo.net/tutorials/SDL/01_hello_SDL/index2.php
My make file is pretty simple (I've stolen it off his website as well)
COMPILER_FLAGS = -w
LINKER_FLAGS = -framework SDL2
#OBJS specifies which files to compile as part of the project
OBJS = main.c
#CC specifies which compiler we're using
CC = g++
OBJ_NAME = main
#This is the target that compiles our executable
all : $(OBJS)
$(CC) $(OBJS) $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)
If anyone knows what I am doing wrong, I'd love to find out.
UPDATE: I pulled out an old laptop, fresh installed to El Capitan and it is having the same issue based on the Lazy Foo code.
UPDATE:
/*This source code copyrighted by Lazy Foo' Productions (2004-2015)
and may not be redistributed without written permission.*/
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main( int argc, char* args[] )
{
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Create window
window = SDL_CreateWindow( "SDL Tutorial", 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() );
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//Update the surface
SDL_UpdateWindowSurface( window );
//Wait two seconds
SDL_Delay( 2000 );
}
}
//Destroy window
SDL_DestroyWindow( window );
//Quit SDL subsystems
SDL_Quit();
return 0;
}
Not sure of the root cause but making a loop that polls events seems to do the trick.
bool loop = true;
while(loop)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
loop = false;
}
}
}

Multiple SDL windows with YUV Overlay

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.

Resources