This reintroduces the fix from 0e16ee8330, but just marks
the viewport state as dirty after a clear that needs to expand the
viewport to fill the render target, as we'll need to also reset
the orthographic projection state elsewhere, and that won't
happen if we clear the dirty flag here.
Fixes#4210.
(again.)
(...sorry...!)
The Renderer logical scaling code scales mouse coordinates, and needs to
take the window DPI into account on HIGHDPI windows. However, the
variable which tracks this, renderer->dpi_scale, is set once when the
renderer is created, and then not updated. In the event that the window
is moved to another screen, or the screen DPI otherwise changes, this
will be outdates, and potentially the coordinates will be all wrong.
So let's update the dpi_scale on the SIZE_CHANGED event: it's at least a
possibility that this will be issued on some OSes when DPI changes, and
it's otherwise already handled by SDL_Renderer's event filter.
Otherwise you might have set the viewport to the full size of
the render target in SDL's API but this change hasn't been
transmitted to Direct3D yet by the time we attempt to clear.
Fixes#4210.
The RenderDrawLinesWithRects and RenderDrawLinesWithRectsF functions can
sometimes call QueueCmdFillRects() with the data pointed to by frects
uninitialised. This can occur if none of the lines can be replaced with
rects, in which case the frects array is empty, and nrects is 0.
gcc 10.3.0 will detect this possibility, and print a warning like:
/home/david/Development/SDL/src/render/SDL_render.c: In function 'RenderDrawLinesWithRectsF':
/home/david/Development/SDL/src/render/SDL_render.c:2725:15: warning: '<unknown>' may be used uninitialized [-Wmaybe-uninitialized]
2725 | retval += QueueCmdFillRects(renderer, frects, nrects);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/david/Development/SDL/src/render/SDL_render.c:499:1: note: by argument 2 of type 'const SDL_FRect *' to 'QueueCmdFillRects' declared here
499 | QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect * rects, const int count)
| ^~~~~~~~~~~~~~~~~
This is harmless, because when this is uninitialised, nrects is always
0, so QueueCmdFillRects() does nothing anyway. We therefore can work
around this by only calling QueueCmdFillRects() when nrects is nonzero.
Somewhat impressively, gcc recognises that this is now safe.
This is needed to support CHERI, and thus Arm's experimental Morello
prototype, where pointers are implemented using unforgeable capabilities
that include bounds and permissions metadata to provide fine-grained
spatial and referential memory safety, as well as revocation by sweeping
memory to provide heap temporal memory safety.
On most systems (anything with a flat memory hierarchy rather than using
segment-based addressing), size_t and uintptr_t are the same type.
However, on CHERI, size_t is just an integer offset, whereas uintptr_t
is still a capability as described above. Casting a pointer to size_t
will strip the metadata and validity tag, and casting from size_t to a
pointer will result in a null-derived capability whose validity tag is
not set, and thus cannot be dereferenced without faulting.
The audio and cursor casts were harmless as they intend to stuff an
integer into a pointer, but using uintptr_t is the idiomatic way to do
that and silences our compiler warnings (which our build tool makes
fatal by default as they often indicate real problems). The iconv and
egl casts were true positives as SDL_iconv_t and iconv_t are pointer
types, as is NativeDisplayType on most OSes, so this would have trapped
at run time when using the round-tripped pointers. The gles2 casts were
also harmless; the OpenGL API defines this argument to be a pointer type
(and uses the argument name "pointer"), but it in fact represents an
integer offset, so like audio and cursor the additional idiomatic cast
is needed to silence the warning.
Fixes SDL_CreateWindowAndRenderer (and similar situations) not choosing a Metal backend. See #3991.
Passing an explicit backend into CreateWindow, eg SDL_WINDOW_OPENGL or SDL_WINDOW_METAL, will still prevent the window from being used with other backend types.
This is caused by the Metal renderer recreating the window because by default we create an OpenGL window on macOS.
It turns out that at least on macOS 10.15, a window that has been initialized for OpenGL can also be used with Metal. So we'll skip recreating the window in that case.
UMU
#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
I think SDL_STRINGIFY_ARG should be removed.
#define SDL_COMPOSE_ERROR(str) __FUNCTION__ ", " str
(verified with Visual Studio 2019)
C.W. Betts
I tested building commit http://hg.libsdl.org/SDL/rev/7adf3fdc19f3 on Mac Catalyst and found some issues:
* MTLFeatureSet_iOS_* enums aren't available under Mac Catalyst.
* OpenGL ES is unavailable under Mac Catalyst.
* Some Metal features are available under Catalyst but not iOS, such as displaySyncEnabled.
* Set Metal as the default renderer on Mac Catalyst
Attaching a patch that will make SDL2 build for Mac Catalyst.
Vincent Hamm
Xcode11 and ios13 added support for metal simulator.
Here is a quick and dirty patch to enable it. Pretty early and only tested on a few samples for now. Required mostly to enable metal support on correct version of ios, generate simulator compatible shaders and enforce buffer alignments on simulator (same as osx).
OpenGL leaves the final line segment open, SDL's software renderer does not,
so we need a tiny bit of trigonometry here to move one more pixel in the right
direction.
We now handle HiDPI correctly, and touches are clamped to the viewport. So
if you are rendering to a logical 640x480 in a 720p window, and touch the
letterboxing at point (640,700), it will report the touch at (0.5,1.0) instead
of outside the documented range.
This fixes a case where you render to the backbuffer, then render to a render
target, set the current target back to the backbuffer, and then present
without drawing anything else; in this circumstance, the Present command
would never happen.
Fixes Bugzilla #5011.
From hmk:
"When scaling is enabled (e.g. via SDL_RenderSetLogicalSize, size not equal
to window size), mouse motion events are also scaled. Small motions are
rounded up (SDL_max() when the value after scaling is less than 1), while
larger motions are truncated by the floating point -> integer conversion.
https://hg.libsdl.org/SDL/file/b18197f9bf9d/src/render/SDL_render.c#l658
The end result feels something like mouse reverse mouse acceleration + angle
snapping at low speeds, but less consistent (amount of truncation & rounding
depends on how fast the mouse is moved) and potentially much worse if the
scaling factor is large. This pretty much makes it useless for anything
where you need precise mouse aiming (think of games). I suspect this is why
aiming gets so terrible in some games that let you use scaling to reduce the
render resolution (e.g. Ion Fury).
With 4x4 scaling, I can reproduce a situation where it takes three fast flicks
of the mouse across the pad to undo one slow sweep across the pad. In other
words, extreme reverse acceleration. This does not happen when scaling is
disabled.
Furthermore, any game that uses relative mouse motion events for 3D camera
rotation probably wants the raw mouse deltas and not a value that depends on
scaling and resolution and rounding and truncation. Ideal camera rotation
just takes mouse input, multiplies it by sensitivity, and adds it to the
angle-in-radians or whatever measure is used for yaw & pitch. Pixels and
screen resolution or window dimensions should not be a part of the equation
at all, even if it could be implemented without rounding errors.
[...]
This [patch] completely eliminates angle snapping for me, and makes
sensitivity consistent. In other words, it's completely usable for, say,
aiming in a first person shooter."
Partially fixes Bugzilla #4811.
Konrad
It appears that I cannot use SDL_RenderReadPixels on a bound framebuffer (SDL_Texture set as render target) as it simply results in gibberish data. However, drawing that framebuffer into the default target (window surface) does render it correctly. Other backends (OpenGL, software, Direct3D) do work fine.
It looks to me like D3D11_RenderReadPixels just gets the general backbuffer and not the current render target and its backbuffer.
Here is the patch which actually fetches the current render target and its underlying ID3D11Resource which is ID3D11Texture2D.
Otherwise our cached state goes out of sync when updating a texture. Since
these state changes aren't necessary, they were removed instead of updating
the cached state.
Fixes Bugzilla #4998.
cmediaplayer
Hi, i already mentioned in the SDL discourse a bug that recreating of a texture occours pixel shader problem on direct3d renderer. There is no problem for direct3d11. You can see the issue by using my app named C Media Player which is available for Windows for free using my web site www.cmediaplayer.com. Just follow the steps:
*Open a media file
*When playing the file change the scale quality under the video menu.
*You will see the problem.
This is the OpenGL line drawing fix for Bugzilla #3182, but there's some
disagreement about what the renderers should do here, so I'm backing this out
until after 2.0.12 ships, and then we'll reevaluate all the renderer backends
to decide what's correct, and make them all work the same.
Likewise for the GLES1 and GLES2 renderers.
This solves the missing pixel at the end of a line and removes all the
heuristics for various platforms/drivers. It's possible we could still use
GL_LINE_STRIP with this and save some vertex buffer space, assuming this
doesn't upset some driver somewhere, but this seems to be a clean fix that
makes the GL renderers match the software renderer output.
Diamond-exit rule explanation:
http://graphics-software-engineer.blogspot.com/2012/04/rasterization-rules.html
Fixes Bugzilla #3182.
Konrad
This kind of blending is rather quite useful and in my opinion should be available for all renderers. I do need it myself, but since I didn't want to use a custom blending mode which is supported only by certain renderers (e.g. not in software which is quite important for me) I did write implementation of SDL_BLENDMODE_MUL for all renderers altogether.
SDL_BLENDMODE_MUL implements following equation:
dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
dstA = (srcA * dstA) + (dstA * (1-srcA))
Background:
https://i.imgur.com/UsYhydP.png
Blended texture:
https://i.imgur.com/0juXQcV.png
Result for SDL_BLENDMODE_MOD:
https://i.imgur.com/wgNSgUl.png
Result for SDL_BLENDMODE_MUL:
https://i.imgur.com/Veokzim.png
I think I did cover all possibilities within included patch, but I didn't write any tests for SDL_BLENDMODE_MUL, so it would be lovely if someone could do it.
Konrad
This was something rather trivial to add, but asked at least several times before (I did google about it as well).
It should be possible to dynamically change scaling mode of the texture. It is actually trivial task, but until now it was only possible with a hint before creating a texture.
I needed it for my game as well, so I took the liberty of writing it myself.
This patch adds following functions:
SDL_SetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode scaleMode);
SDL_GetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode *scaleMode);
That way you can change texture scaling on the fly.
warning: either cast from 'int' to 'size_t' (aka 'unsigned long') is ineffective, or there is loss of precision before the conversion [bugprone-misplaced-widening-cast]
Sylvain
I think what happening with the software renderer is:
* you're somehow in background (so texture creation is not possible)
* it resizes and wants to push a SDL_WINDOWEVENT_SIZE_CHANGED
It call:
https://hg.libsdl.org/SDL/file/a010811d40dd/src/render/SDL_render.c#l683
* GetOutputSize
* SW_GetOutputSize
* SW_ActivateRenderer
* SDL_GetWindowSurface
* SDL_CreateWindowFramebuffer which is mapped to SDL_CreateWindowTexture
and it ends up re-creating the surface/a texture, while being in background
Sylvain
Currently SDL_CreateTextureFromSurface picks first valid format, and do a conversion.
format = renderer->info.texture_formats[0];
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
format = renderer->info.texture_formats[i];
break;
It could try to find a better format, for instance :
if SDL_Surface has no Amask, but a colorkey :
if surface fmt is RGB888, try to pick ARGB8888 renderer fmt
if surface fmt is BGR888, try to pick ABGR8888 renderer fmt
else
try to pick the same renderer format as surface fmt
if no format has been picked, use the fallback.
I think it goes with bug 4290 fastpath BlitNtoN
when you expand a surface with pixel format of size 24 to 32, there is a fast path possible.
So with this issue:
- if you have a surface with colorkey (RGB or BGR, not palette), it takes a renderer format where the conversion is faster.
(it avoids, if possible, RGB -> ABGR which means switching RGB to BGR)
- if you have a surface ABGR format, it try to take the ABGR from the renderer.
(it avoids, if possible, ABGR -> ARGB, which means switch RGB to BGR)
Sylvain
OpenGLES2 SDL renderer has support for textures ARGB, ABGR, RGB and BGR, whereas OpenGL SDL renderer only had ARGB.
If you think it's worth adding it, here's a patch. I quickly tried and it worked, but there may be missing things or corner case.
This is the best option for macOS and iOS, the only platforms with Metal.
Pre-Metal versions of these platforms will fall back to OpenGL (ES), as
appropriate.
Huge thanks to Alexander Szpakowski, who worked incredibly hard to get the
Metal renderer to such a high-quality state!
./src/render/SDL_render.c(2168): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2168): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2175): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2175): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2322): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2322): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2322): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2322): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2329): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2329): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2329): Error! E1054: Expression must be constant
./src/render/SDL_render.c(2329): Error! E1054: Expression must be constant
./src/render/software/SDL_render_sw.c(602): Error! E1054: Expression must be constant
./src/render/software/SDL_render_sw.c(602): Error! E1054: Expression must be constant
./src/render/software/SDL_render_sw.c(602): Error! E1054: Expression must be constant
./src/render/software/SDL_render_sw.c(602): Error! E1054: Expression must be constant
https://bugzilla.libsdl.org/show_bug.cgi?id=4350
We can't safely call GL_DestroyRenderer() until GL_LoadFunctions()
succeeds because we will be missing functions that we try to use
when activating the renderer for destruction if we have an GL context.
Sylvain
Re-opening this issue.
It fixes the test-case, but it introduces a regression with another bug (bug #4313).
So here's a new patch that activate cropping of the source surface to solve the issue.
It also reverts the wrong changeset.
It prevents unneeded colorkey error message.
Include guards in most changed files were missing, I added them keeping
the same style as other SDL files. In some cases I moved the include
guards around to be the first thing the header has to take advantage of
any possible improvements compiler may have for inclusion guards.
I have no idea if this works (or if it ever worked, having now examined this
code), as I have no way to compile or test this.
If it's broken, send patches. :)
This means it doesn't have to block while the current frame finishes using the
vertex buffer; it just moves on to the next, probably-not-in-use buffer.
- high-level filters out duplicate render commands from the queue so
backends don't have to.
- Setting draw color is now a render command, so backends can put color
information into the vertex buffer to upload with everything else instead
of setting it with slower dynamic data later.
- backends can request that they always batch, even for legacy programs,
since the lowlevel API can deal with it (Metal, and eventually Vulkan
and such...)
- high-level makes sure the queue has at least one setdrawcolor and
setviewport command before any draw calls, so the backends don't ever have
to manage cases where this hasn't been explicitly set yet.
- backends allocating vertex buffer space can specify alignment, and the
high-level will keep track of gaps in the buffer between the last used
positions and the aligned data that can be used for later allocations
(Metal and such need to specify some constant data on 256 byte boundaries,
but we don't want to waste all that space we had to skip to meet alignment
requirements).
It now uses a growable linked list that keeps a pool of allocated items for
reuse, and reallocs the vertex array as necessary. Testsprite2 can scale to
20,000 (or more!) draws now without drama.
This moves all the rendering to a command list that is flushed to the GL as
necessary, making most common activities upload a single vertex buffer per
frame and dramatically reducing state changes. In pathological cases,
like Emscripten running on iOS's Safari, performance can go from a dozen
draw calls killing your performance to 1000 draw calls running smoothly.
This is work in progress, and not ready to ship. Among other things, it has
a hardcoded array that isn't checked for overflow. But the basic idea is
sound!
The only place angle is activated and causes effect is RenderCopyEx. All other
methods which use vertex shader, leave angle disabled and cause useless sin/cos
calculation in shader.
To get around shader's interface is changed to a vector that contains results
of sin and cos. To behave properly when disabled, cos value is set with offset
-1.0 making 0.0 default when deactivated.
As nice side effect it simplifies GLES2_UpdateVertexBuffer: All attributes are
vectors now.
Additional background:
* On RaspberryPi it gives a performace win for operations. Tested with
[1] numbers go down for 5-10% (not easy to estimate due to huge variation).
* SDL_RenderCopyEx was tested with [2]
* It works around left rotated display caused by low accuracy sin implemetation
in RaspberryPi/VC4 [3]
[1] https://github.com/schnitzeltony/sdl2box
[2] https://github.com/schnitzeltony/sdl2rendercopyex
[3] https://github.com/anholt/mesa/issues/110
Signed-off-by: Andreas M?ller <schnitzeltony@gmail.com>
duckgrease
SDL_RenderCopyEx blits wrong image (in some cases it's bunch of alternating horizontal lines, some cases it's image from the wrong coordinate, and in some cases it's just a bunch of garbled pixels), when the following conditions are met:
- Use software renderer.
- Enable either horizontal or vertical flip.
- source and destination rectangles must have same width and height, and must be smaller than the size of the texture.
- source rectangle's X and Y coordinates must be 0.
Sylvain
Patch a few warnings when using:
-Wmissing-prototypes -Wdocumentation -Wdocumentation-unknown-command
They are automatically enabled with -Wall
Anthony @ POW Games
SDL_CreateTextureFromSurface makes an internal call to SDL_GetColorKey which can return an error and spams the error log with "Surface doesn't have a colorkey" even though the original function didn't return an error.
Olli-Samuli Lehmus
If one creates a window with the SDL_WINDOW_FULLSCREEN_DESKTOP flag, and creates a render target with SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"), and afterwards sets SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"), after minimizing the window, the scale quality hint is lost on the render target. Textures however do keep their interpolation modes.
SDL now builds with gcc 7.2 with the following command line options:
-Wall -pedantic-errors -Wno-deprecated-declarations -Wno-overlength-strings --std=c99
- Use a single buffer for various non-changing constants accessed by the GPU, instead of multiple buffers.
- Do the half-pixel offset for points and lines using a transform matrix so we don't need a malloc when rendering.
- Don't add a half-pixel offset for other primitives and textures. This matches D3D and GL render behaviour.
- Remove the half-texel texture coordinate offset since it's not needed now that there's no more half-pixel position offset when rendering a texture.
- Don't try to set texture usage on iOS 8 since it doesn't exist there.
Eric wing
There is a tiny bug in the new overscan code for the SDL_renderer.
In SDL_renderer.c, line 1265, the if check for SDL_strcasecmp with "direct3d" needs to be inverted.
Instead of:
if(SDL_strcasecmp("direct3d", SDL_GetCurrentVideoDriver())) {
It should be:
if(0 == SDL_strcasecmp("direct3d", SDL_GetCurrentVideoDriver())) {
This bug causes the "overscan" mode to pretty much be completely ignored in all cases and all things remain letterboxed (as before the feature).