Can cairo use SDL_Texture as a render target? - sdl

Rendering to an SDL_Surface is possible with Cairo, but my application uses SDL_Renderer and SDL_Texture to take advantage of 2D accelerated rendering.
I am currently creating an SDL_Surface and copying it to a texture with SDL_CreateTextureFromSurface(), but this process is cumbersome and possibly slow (although it's not a bottleneck.) Is there a direct way to draw to a SDL_Texture?

I've figured it out. Streaming SDL_Textures can expose the raw pixels in the ARGB8888 format, which is a format Cairo surfaces can also handle. The Cairo API is low level enough to only require the pixel buffer and pitch.
SDL_Texture *texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
width, height);
void *pixels;
int pitch;
SDL_LockTexture(texture, NULL, &pixels, &pitch);
cairo_surface_t *cairo_surface = cairo_image_surface_create_for_data(
pixels,
CAIRO_FORMAT_ARGB32,
width, height, pitch);
paint(cairo_create(cairo_surface));
SDL_UnlockTexture(texture);
How convenient.

Related

stretching image in sdl2

Is stretching image in sdl2 makes the program slower?
For example if my map tile's native resolution is 32x32 and I stretch it in sdl to and make it 64x64, will it affect the program's speed?
Here's how I load my image:
SDL_Surface *surface = NULL;
SDL_Texture *texture = NULL;
surface = IMG_Load("sample.png");//this is the 32x32 image
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_Rect dstRect = {0, 0, 64, 64};//and I will use this rect for that sample.png in SDL_RenderCopy();
Yes, if will be resized each time when repainting. If you need to have resized tile, you should create cache with resized tiles (resize it on start, and use the cached tile on repaint). SDL_BlitScaled for surface, or SDL_CreateTexture(surface, format, target, width, height) for texture can be used to do it.

SDL2 Draw scene to texture. SDL2 RenderTexture like SFML

I've been developing a 2D Engine using SFML + ImGui.
The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine.
I've managed to render the editor like I did in the 2D Engine using this Example that comes with ImGui.
But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
If you can provide code will be better. And if you want me to provide any specific code tell me.
Here's my solution.
SDL2window::SDL2window()
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(...);
renderer = SDL_CreateRenderer(window,...);
texture = SDL_CreateTexture(renderer,..., width, height);
// create another texture for your imgui window here
ImTexture = SDL_CreateTexture(renderer,..., tex_width, tex_height);
...
}
void SDL2window::update(Uint32 *framebuffer)
{
...
// update your main window is necessary
SDL_RenderCopyEx(renderer, texture, NULL, NULL, 0, 0, SDL_FLIP_VERTICAL);
// be care of the size of framebuffer
SDL_UpdateTexture(ImTexture, NULL, framebuffer, tex_width * sizeof(Uint32));
ImGui::Render();
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(renderer);
}
void SDL2window::MyImgui()
{
...
ImGui::Begin("My Texture");
ImGui::Image(ImTexture, ImVec2(tex_width, tex_height));
ImGui::End();
}
Then run MyImgui() in your main loop, it will work.
ImTexture Window
P.S. I like your SFML 2D engine's UI, it looks great.
Think you're looking for something like this:
// Create a render texture
SDL_Texture *target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
// Activate the render texture
SDL_SetRenderTarget(renderer, target);
// (Do your rendering here)
// Disable the render texture
SDL_SetRenderTarget(renderer, NULL);
// (Use the render texture)

Set the pixel format AND create texture from surface in SDL

I am currently trying some things using pixel manipulation and I would like to set the pixel format of a SDL_Surface. The problem here is that I am loading up an image with the SDL_image.h. So I have to create a texture from a surface like this:
surface = IMG_Load(filePath);
texture = SDL_CreateTextureFromSurface(renderer, surface);
So I can't use the following function, which I would like to, or can I?:
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 480);
The thing is, that I want to set the SDL_PixelFormat to be able to mess around with the pixels. How can I both do this and create the texture based on a surface?
The SDL2 API provides the function SDL_ConvertSurface:
SDL_Surface* SDL_ConvertSurface(SDL_Surface* src,
const SDL_PixelFormat* fmt,
Uint32 flags)
You should be able to do
surface = IMG_Load(filePath);
// Call SDL_ConvertSurface to set the pixel format of the surface you have created.
texture = SDL_CreateTextureFromSurface(renderer, surface);
Reference: https://wiki.libsdl.org/SDL_ConvertSurface

SDL draws images blurred without scaling

I'm working on a project in C++ using SDL (Simple Directmedia Layer) but when I draw a SDL_Texture to the screen it's blurred eventhough it is not scaled.
How the image is loaded:
SDL_Surface* loadedSurface = IMG_Load("image.png");
SDL_Texture* gImage = SDL_CreateTextureFromSurface( gRenderer, loadedSurface);
How the image is drawn to the screen:
SDL_Rect renderQuad = { x, y, width, height };
SDL_RenderCopy(gRenderer, gImage , NULL, &renderQuad );
See image, left is in the program and right is the original:
Is there a parameter a forgot to set? And is it normal that SDL does this?
I'm using SDL 2.0 32-bit on a Windows 8.1 64-bit machine.
Ahead of your call to SDL_CreateTextureFromSurface try calling:
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
According to SDL Wiki this should affect how SDL_CreateTextureFromSurface calls interpolate the surface. "0" should result in nearest neighbour removing the blurring effect you are seeing.

How to draw screenshot captured from glReadPixels to wxWidgets dialog/panel

I have an OpenGL window, and a wxWidget dialog. I want to mirror the OpenGL to the dialog. So what I intend to do is:
Capture the screenshot of the opengl
Display it onto the wxwidgets dialog.
Any idea?
Update: This is how I currently use glReadPixels (I also temporarily use FreeImage to save to BMP file, but I expect the file saving to be removed if there's a way to channel it directly to the wxImage)
// Make the BYTE array, factor of 3 because it's RBG.
BYTE* pixels = new BYTE[ 3 * width * height];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
// Convert to FreeImage format & save to file
FIBITMAP* image = FreeImage_ConvertFromRawBits(pixels, width, height, 3 * width, 24, 0x0000FF, 0xFF0000, 0x00FF00, false);
FreeImage_Save(FIF_BMP, image, "C:/test.bmp", 0);
// Free memory
delete image;
delete pixels;
// Add Image Support for all types
wxInitAllImageHandlers();
BYTE* pixels = new BYTE[ 3 * width * height];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
// width height pixels alpha
wxImage img(with, height, pixels, NULL); // I am not sure if NULL is permitted on the alpha channel, but you can test that yourself :).
// Second method:
wxImage img(width, heiht, true);
img.SetData(pixels);
You can now use the image for displaying, saving as jpg png bmp whatever you like. For just displaying in a dialog, you don't need to save it to the harddisc though but of course, you can.
Just create the image on the heap then.
http://docs.wxwidgets.org/stable/wx_wximage.html#wximagector
Hope it helps