Merge SDL-ryan-batching-renderer branch to default.

--HG--
extra : rebase_source : 83b86d35497a01be6f48055490580bbba19ccc7a
extra : amend_source : faae1a04859499ede43aba3ba50fc4f62b5afbcb
This commit is contained in:
Ryan C. Gordon 2018-10-31 15:03:41 -04:00
commit 9f99a9c642
38 changed files with 6953 additions and 5554 deletions

View file

@ -1043,6 +1043,31 @@ extern "C" {
*/
#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
/**
* \brief A variable controlling whether the 2D render API is compatible or efficient.
*
* This variable can be set to the following values:
*
* "0" - Don't use batching to make rendering more efficient.
* "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls.
*
* Up to SDL 2.0.9, the render API would draw immediately when requested. Now
* it batches up draw requests and sends them all to the GPU only when forced
* to (during SDL_RenderPresent, when changing render targets, by updating a
* texture that the batch needs, etc). This is significantly more efficient,
* but it can cause problems for apps that expect to render on top of the
* render API's output. As such, SDL will disable batching if a specific
* render backend is requested (since this might indicate that the app is
* planning to use the underlying graphics API directly). This hint can
* be used to explicitly request batching in this instance. It is a contract
* that you will either never use the underlying graphics API directly, or
* if you do, you will call SDL_RenderFlush() before you do so any current
* batch goes to the GPU before your work begins. Not following this contract
* will result in undefined behavior.
*/
#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING"
/**
* \brief An enumeration of hint priorities
*/

View file

@ -40,7 +40,7 @@ extern "C" {
#endif
/**
* \brief The structure that defines a point
* \brief The structure that defines a point (integer)
*
* \sa SDL_EnclosePoints
* \sa SDL_PointInRect
@ -52,7 +52,20 @@ typedef struct SDL_Point
} SDL_Point;
/**
* \brief A rectangle, with the origin at the upper left.
* \brief The structure that defines a point (floating point)
*
* \sa SDL_EnclosePoints
* \sa SDL_PointInRect
*/
typedef struct SDL_FPoint
{
float x;
float y;
} SDL_FPoint;
/**
* \brief A rectangle, with the origin at the upper left (integer).
*
* \sa SDL_RectEmpty
* \sa SDL_RectEquals
@ -67,6 +80,19 @@ typedef struct SDL_Rect
int w, h;
} SDL_Rect;
/**
* \brief A rectangle, with the origin at the upper left (floating point).
*/
typedef struct SDL_FRect
{
float x;
float y;
float w;
float h;
} SDL_FRect;
/**
* \brief Returns true if point resides inside a rectangle.
*/

View file

@ -835,6 +835,148 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
const SDL_Point *center,
const SDL_RendererFlip flip);
/**
* \brief Draw a point on the current rendering target.
*
* \param renderer The renderer which should draw a point.
* \param x The x coordinate of the point.
* \param y The y coordinate of the point.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer,
float x, float y);
/**
* \brief Draw multiple points on the current rendering target.
*
* \param renderer The renderer which should draw multiple points.
* \param points The points to draw
* \param count The number of points to draw
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer,
const SDL_FPoint * points,
int count);
/**
* \brief Draw a line on the current rendering target.
*
* \param renderer The renderer which should draw a line.
* \param x1 The x coordinate of the start point.
* \param y1 The y coordinate of the start point.
* \param x2 The x coordinate of the end point.
* \param y2 The y coordinate of the end point.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer,
float x1, float y1, float x2, float y2);
/**
* \brief Draw a series of connected lines on the current rendering target.
*
* \param renderer The renderer which should draw multiple lines.
* \param points The points along the lines
* \param count The number of points, drawing count-1 lines
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer,
const SDL_FPoint * points,
int count);
/**
* \brief Draw a rectangle on the current rendering target.
*
* \param renderer The renderer which should draw a rectangle.
* \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer,
const SDL_FRect * rect);
/**
* \brief Draw some number of rectangles on the current rendering target.
*
* \param renderer The renderer which should draw multiple rectangles.
* \param rects A pointer to an array of destination rectangles.
* \param count The number of rectangles.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects,
int count);
/**
* \brief Fill a rectangle on the current rendering target with the drawing color.
*
* \param renderer The renderer which should fill a rectangle.
* \param rect A pointer to the destination rectangle, or NULL for the entire
* rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer,
const SDL_FRect * rect);
/**
* \brief Fill some number of rectangles on the current rendering target with the drawing color.
*
* \param renderer The renderer which should fill multiple rectangles.
* \param rects A pointer to an array of destination rectangles.
* \param count The number of rectangles.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer,
const SDL_FRect * rects,
int count);
/**
* \brief Copy a portion of the texture to the current rendering target.
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_FRect * dstrect);
/**
* \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
* \param angle An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction
* \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2).
* \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_FRect * dstrect,
const double angle,
const SDL_FPoint *center,
const SDL_RendererFlip flip);
/**
* \brief Read pixels from the current rendering target.
*
@ -876,6 +1018,31 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture);
*/
extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer);
/**
* \brief Force the rendering context to flush any pending commands to the
* underlying rendering API.
*
* You do not need to (and in fact, shouldn't) call this function unless
* you are planning to call into OpenGL/Direct3D/Metal/whatever directly
* in addition to using an SDL_Renderer.
*
* This is for a very-specific case: if you are using SDL's render API,
* you asked for a specific renderer backend (OpenGL, Direct3D, etc),
* you set SDL_HINT_RENDER_BATCHING to "1", and you plan to make
* OpenGL/D3D/whatever calls in addition to SDL render API calls. If all of
* this applies, you should call SDL_RenderFlush() between calls to SDL's
* render API and the low-level API you're using in cooperation.
*
* In all other cases, you can ignore this function. This is only here to
* get maximum performance out of a specific situation. In all other cases,
* SDL will do the right thing, perhaps at a performance loss.
*
* This function is first available in SDL 2.0.10, and is not needed in
* 2.0.9 and earlier, as earlier versions did not queue rendering commands
* at all, instead flushing them to the OS immediately.
*/
extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer);
/**
* \brief Bind the texture to the current OpenGL/ES/ES2 context for use with

View file

@ -178,6 +178,7 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
(void) userdata; /* unused in default handler. */
/* !!! FIXME: why is this using SDL_stack_alloc and not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (!message) {
/* Uh oh, we're in real trouble now... */

View file

@ -35,6 +35,10 @@
#define SDL_VARIABLE_LENGTH_ARRAY
#endif
#define SDL_MAX_SMALL_ALLOC_STACKSIZE 128
#define SDL_small_alloc(type, count, pisstack) ( (*(pisstack) = ((sizeof(type)*(count)) < SDL_MAX_SMALL_ALLOC_STACKSIZE)), (*(pisstack) ? SDL_stack_alloc(type, count) : (type*)SDL_malloc(sizeof(type)*(count))) )
#define SDL_small_free(ptr, isstack) if ((isstack)) { SDL_stack_free(ptr); } else { SDL_free(ptr); }
#include "dynapi/SDL_dynapi.h"
#if SDL_DYNAMIC_API

View file

@ -282,6 +282,7 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list
return;
}
/* !!! FIXME: why not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (!message) {
return;
@ -321,6 +322,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
char *output;
size_t length;
LPTSTR tstr;
SDL_bool isstack;
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
BOOL attachResult;
@ -364,7 +366,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
output = SDL_stack_alloc(char, length);
output = SDL_small_alloc(char, length, &isstack);
SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
tstr = WIN_UTF8ToString(output);
@ -389,7 +391,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
SDL_free(tstr);
SDL_stack_free(output);
SDL_small_free(output, isstack);
}
#elif defined(__ANDROID__)
{
@ -404,7 +406,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
extern void SDL_NSLog(const char *text);
{
char *text;
/* !!! FIXME: why not just "char text[SDL_MAX_LOG_MESSAGE];" ? */
text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (text) {
SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);

View file

@ -481,10 +481,11 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls,
int argc;
int len;
char **argv;
SDL_bool isstack;
/* Prepare the arguments. */
len = (*env)->GetArrayLength(env, array);
argv = SDL_stack_alloc(char*, 1 + len + 1);
argv = SDL_small_alloc(char*, 1 + len + 1, &isstack); /* !!! FIXME: check for NULL */
argc = 0;
/* Use the name "app_process" so PHYSFS_platformCalcBaseDir() works.
https://bitbucket.org/MartinFelis/love-android-sdl2/issue/23/release-build-crash-on-start
@ -517,7 +518,7 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls,
for (i = 0; i < argc; ++i) {
SDL_free(argv[i]);
}
SDL_stack_free(argv);
SDL_small_free(argv, isstack);
} else {
__android_log_print(ANDROID_LOG_ERROR, "SDL", "nativeRunMain(): Couldn't find function %s in library %s", function_name, library_file);

View file

@ -701,3 +701,14 @@
#define SDL_JoystickGetDevicePlayerIndex SDL_JoystickGetDevicePlayerIndex_REAL
#define SDL_JoystickGetPlayerIndex SDL_JoystickGetPlayerIndex_REAL
#define SDL_GameControllerGetPlayerIndex SDL_GameControllerGetPlayerIndex_REAL
#define SDL_RenderFlush SDL_RenderFlush_REAL
#define SDL_RenderDrawPointF SDL_RenderDrawPointF_REAL
#define SDL_RenderDrawPointsF SDL_RenderDrawPointsF_REAL
#define SDL_RenderDrawLineF SDL_RenderDrawLineF_REAL
#define SDL_RenderDrawLinesF SDL_RenderDrawLinesF_REAL
#define SDL_RenderDrawRectF SDL_RenderDrawRectF_REAL
#define SDL_RenderDrawRectsF SDL_RenderDrawRectsF_REAL
#define SDL_RenderFillRectF SDL_RenderFillRectF_REAL
#define SDL_RenderFillRectsF SDL_RenderFillRectsF_REAL
#define SDL_RenderCopyF SDL_RenderCopyF_REAL
#define SDL_RenderCopyExF SDL_RenderCopyExF_REAL

View file

@ -755,3 +755,14 @@ SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a,
SDL_DYNAPI_PROC(int,SDL_JoystickGetDevicePlayerIndex,(int a),(a),return)
SDL_DYNAPI_PROC(int,SDL_JoystickGetPlayerIndex,(SDL_Joystick *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GameControllerGetPlayerIndex,(SDL_GameController *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawPointF,(SDL_Renderer *a, float b, float c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawPointsF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawLineF,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawLinesF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_RenderDrawRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderFillRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_RenderFillRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_RenderCopyF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(int,SDL_RenderCopyExF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_RendererFlip g),(a,b,c,d,e,f,g),return)

View file

@ -528,6 +528,7 @@ SDL_RWFromFile(const char *file, const char *mode)
char *path;
FILE *fp;
/* !!! FIXME: why not just "char path[PATH_MAX];" ? */
path = SDL_stack_alloc(char, PATH_MAX);
if (path) {
SDL_snprintf(path, PATH_MAX, "%s/%s",

View file

@ -202,13 +202,14 @@ static void UpdateEventsForDeviceRemoval()
{
int i, num_events;
SDL_Event *events;
SDL_bool isstack;
num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
if (num_events <= 0) {
return;
}
events = SDL_stack_alloc(SDL_Event, num_events);
events = SDL_small_alloc(SDL_Event, num_events, &isstack);
if (!events) {
return;
}
@ -219,7 +220,7 @@ static void UpdateEventsForDeviceRemoval()
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
SDL_stack_free(events);
SDL_small_free(events, isstack);
}
static SDL_bool HasSameOutput(SDL_ExtendedGameControllerBind *a, SDL_ExtendedGameControllerBind *b)

View file

@ -777,13 +777,14 @@ static void UpdateEventsForDeviceRemoval()
{
int i, num_events;
SDL_Event *events;
SDL_bool isstack;
num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
if (num_events <= 0) {
return;
}
events = SDL_stack_alloc(SDL_Event, num_events);
events = SDL_small_alloc(SDL_Event, num_events, &isstack);
if (!events) {
return;
}
@ -794,7 +795,7 @@ static void UpdateEventsForDeviceRemoval()
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
SDL_stack_free(events);
SDL_small_free(events, isstack);
}
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)

View file

@ -61,12 +61,13 @@ SDL_LoadFunction(void *handle, const char *name)
void *symbol = dlsym(handle, name);
if (symbol == NULL) {
/* append an underscore for platforms that need that. */
SDL_bool isstack;
size_t len = 1 + SDL_strlen(name) + 1;
char *_name = SDL_stack_alloc(char, len);
char *_name = SDL_small_alloc(char, len, &isstack);
_name[0] = '_';
SDL_strlcpy(&_name[1], name, len);
symbol = dlsym(handle, _name);
SDL_stack_free(_name);
SDL_small_free(_name, isstack);
if (symbol == NULL) {
SDL_SetError("Failed loading %s: %s", name,
(const char *) dlerror());

File diff suppressed because it is too large Load diff

View file

@ -39,20 +39,6 @@ typedef enum
SDL_ScaleModeBest
} SDL_ScaleMode;
typedef struct
{
float x;
float y;
} SDL_FPoint;
typedef struct
{
float x;
float y;
float w;
float h;
} SDL_FRect;
/* Define the SDL texture structure */
struct SDL_Texture
{
@ -75,12 +61,63 @@ struct SDL_Texture
int pitch;
SDL_Rect locked_rect;
Uint32 last_command_generation; /* last command queue generation this texture was in. */
void *driverdata; /**< Driver specific texture representation */
SDL_Texture *prev;
SDL_Texture *next;
};
typedef enum
{
SDL_RENDERCMD_NO_OP,
SDL_RENDERCMD_SETVIEWPORT,
SDL_RENDERCMD_SETCLIPRECT,
SDL_RENDERCMD_SETDRAWCOLOR,
SDL_RENDERCMD_CLEAR,
SDL_RENDERCMD_DRAW_POINTS,
SDL_RENDERCMD_DRAW_LINES,
SDL_RENDERCMD_FILL_RECTS,
SDL_RENDERCMD_COPY,
SDL_RENDERCMD_COPY_EX
} SDL_RenderCommandType;
typedef struct SDL_RenderCommand
{
SDL_RenderCommandType command;
union {
struct {
size_t first;
SDL_Rect rect;
} viewport;
struct {
SDL_bool enabled;
SDL_Rect rect;
} cliprect;
struct {
size_t first;
size_t count;
Uint8 r, g, b, a;
SDL_BlendMode blend;
SDL_Texture *texture;
} draw;
struct {
size_t first;
Uint8 r, g, b, a;
} color;
} data;
struct SDL_RenderCommand *next;
} SDL_RenderCommand;
typedef struct SDL_AllocVertGap
{
size_t offset;
size_t len;
struct SDL_AllocVertGap *next;
} SDL_AllocVertGap;
/* Define the SDL renderer structure */
struct SDL_Renderer
{
@ -90,12 +127,20 @@ struct SDL_Renderer
int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
SDL_bool (*SupportsBlendMode)(SDL_Renderer * renderer, SDL_BlendMode blendMode);
int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
int (*SetTextureColorMod) (SDL_Renderer * renderer,
SDL_Texture * texture);
int (*SetTextureAlphaMod) (SDL_Renderer * renderer,
SDL_Texture * texture);
int (*SetTextureBlendMode) (SDL_Renderer * renderer,
SDL_Texture * texture);
int (*QueueSetViewport) (SDL_Renderer * renderer, SDL_RenderCommand *cmd);
int (*QueueSetDrawColor) (SDL_Renderer * renderer, SDL_RenderCommand *cmd);
int (*QueueDrawPoints) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points,
int count);
int (*QueueDrawLines) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points,
int count);
int (*QueueFillRects) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects,
int count);
int (*QueueCopy) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
int (*QueueCopyEx) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
int (*RunCommandQueue) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
@ -108,20 +153,6 @@ struct SDL_Renderer
const SDL_Rect * rect, void **pixels, int *pitch);
void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture);
int (*UpdateViewport) (SDL_Renderer * renderer);
int (*UpdateClipRect) (SDL_Renderer * renderer);
int (*RenderClear) (SDL_Renderer * renderer);
int (*RenderDrawPoints) (SDL_Renderer * renderer, const SDL_FPoint * points,
int count);
int (*RenderDrawLines) (SDL_Renderer * renderer, const SDL_FPoint * points,
int count);
int (*RenderFillRects) (SDL_Renderer * renderer, const SDL_FRect * rects,
int count);
int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch);
void (*RenderPresent) (SDL_Renderer * renderer);
@ -178,6 +209,26 @@ struct SDL_Renderer
Uint8 r, g, b, a; /**< Color for drawing operations values */
SDL_BlendMode blendMode; /**< The drawing blend mode */
SDL_bool always_batch;
SDL_bool batching;
SDL_RenderCommand *render_commands;
SDL_RenderCommand *render_commands_tail;
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
Uint32 last_queued_color;
SDL_Rect last_queued_viewport;
SDL_Rect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool viewport_queued;
SDL_bool cliprect_queued;
void *vertex_data;
size_t vertex_data_used;
size_t vertex_data_allocation;
SDL_AllocVertGap vertex_data_gaps;
SDL_AllocVertGap *vertex_data_gaps_pool;
void *driverdata;
};
@ -209,6 +260,11 @@ extern SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode);
extern SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode);
extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode);
/* drivers call this during their Queue*() methods to make space in a array that are used
for a vertex buffer during RunCommandQueue(). Pointers returned here are only valid until
the next call, because it might be in an array that gets realloc()'d. */
extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset);
#endif /* SDL_sysrender_h_ */
/* vi: set ts=4 sw=4 expandtab: */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -340,11 +340,12 @@ CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, co
ctx->glCompileShaderARB(shader);
ctx->glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
if (status == 0) {
SDL_bool isstack;
GLint length;
char *info;
ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
info = SDL_stack_alloc(char, length+1);
info = SDL_small_alloc(char, length+1, &isstack);
ctx->glGetInfoLogARB(shader, length, NULL, info);
SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
@ -352,7 +353,7 @@ CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, co
fprintf(stderr,
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
#endif
SDL_stack_free(info);
SDL_small_free(info, isstack);
return SDL_FALSE;
} else {

View file

@ -27,6 +27,7 @@
/* OpenGL shader implementation */
typedef enum {
SHADER_INVALID = -1,
SHADER_NONE,
SHADER_SOLID,
SHADER_RGB,

File diff suppressed because it is too large Load diff

View file

@ -75,6 +75,7 @@ SDL_PROC(void, glDeleteFramebuffers, (GLsizei, const GLuint *))
SDL_PROC(GLint, glGetAttribLocation, (GLuint, const GLchar *))
SDL_PROC(void, glGetProgramInfoLog, (GLuint, GLsizei, GLsizei*, GLchar*))
SDL_PROC(void, glGenBuffers, (GLsizei, GLuint *))
SDL_PROC(void, glDeleteBuffers, (GLsizei, GLuint *))
SDL_PROC(void, glBindBuffer, (GLenum, GLuint))
SDL_PROC(void, glBufferData, (GLenum, GLsizeiptr, const GLvoid *, GLenum))
SDL_PROC(void, glBufferSubData, (GLenum, GLintptr, GLsizeiptr, const GLvoid *))

File diff suppressed because it is too large Load diff

View file

@ -69,13 +69,13 @@ static const Uint8 GLES2_FragmentSrc_SolidSrc_[] = " \
static const Uint8 GLES2_FragmentSrc_TextureABGRSrc_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_modulation; \
uniform vec4 u_color; \
varying vec2 v_texCoord; \
\
void main() \
{ \
gl_FragColor = texture2D(u_texture, v_texCoord); \
gl_FragColor *= u_modulation; \
gl_FragColor *= u_color; \
} \
";
@ -83,7 +83,7 @@ static const Uint8 GLES2_FragmentSrc_TextureABGRSrc_[] = " \
static const Uint8 GLES2_FragmentSrc_TextureARGBSrc_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_modulation; \
uniform vec4 u_color; \
varying vec2 v_texCoord; \
\
void main() \
@ -92,7 +92,7 @@ static const Uint8 GLES2_FragmentSrc_TextureARGBSrc_[] = " \
gl_FragColor = abgr; \
gl_FragColor.r = abgr.b; \
gl_FragColor.b = abgr.r; \
gl_FragColor *= u_modulation; \
gl_FragColor *= u_color; \
} \
";
@ -100,7 +100,7 @@ static const Uint8 GLES2_FragmentSrc_TextureARGBSrc_[] = " \
static const Uint8 GLES2_FragmentSrc_TextureRGBSrc_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_modulation; \
uniform vec4 u_color; \
varying vec2 v_texCoord; \
\
void main() \
@ -110,7 +110,7 @@ static const Uint8 GLES2_FragmentSrc_TextureRGBSrc_[] = " \
gl_FragColor.r = abgr.b; \
gl_FragColor.b = abgr.r; \
gl_FragColor.a = 1.0; \
gl_FragColor *= u_modulation; \
gl_FragColor *= u_color; \
} \
";
@ -118,7 +118,7 @@ static const Uint8 GLES2_FragmentSrc_TextureRGBSrc_[] = " \
static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_modulation; \
uniform vec4 u_color; \
varying vec2 v_texCoord; \
\
void main() \
@ -126,7 +126,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
vec4 abgr = texture2D(u_texture, v_texCoord); \
gl_FragColor = abgr; \
gl_FragColor.a = 1.0; \
gl_FragColor *= u_modulation; \
gl_FragColor *= u_color; \
} \
";
@ -163,7 +163,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
"uniform sampler2D u_texture;\n" \
"uniform sampler2D u_texture_u;\n" \
"uniform sampler2D u_texture_v;\n" \
"uniform vec4 u_modulation;\n" \
"uniform vec4 u_color;\n" \
"varying vec2 v_texCoord;\n" \
"\n" \
@ -185,7 +185,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= u_modulation;\n" \
" gl_FragColor *= u_color;\n" \
"}" \
#define NV12_SHADER_BODY \
@ -205,7 +205,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= u_modulation;\n" \
" gl_FragColor *= u_color;\n" \
"}" \
#define NV21_SHADER_BODY \
@ -225,7 +225,7 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= u_modulation;\n" \
" gl_FragColor *= u_color;\n" \
"}" \
/* YUV to ABGR conversion */
@ -284,13 +284,13 @@ static const Uint8 GLES2_FragmentSrc_TextureExternalOESSrc_[] = " \
#extension GL_OES_EGL_image_external : require\n\
precision mediump float; \
uniform samplerExternalOES u_texture; \
uniform vec4 u_modulation; \
uniform vec4 u_color; \
varying vec2 v_texCoord; \
\
void main() \
{ \
gl_FragColor = texture2D(u_texture, v_texCoord); \
gl_FragColor *= u_modulation; \
gl_FragColor *= u_color; \
} \
";

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,7 @@
#include "../SDL_sysrender.h"
#include "SDL_render_sw_c.h"
#include "SDL_hints.h"
#include "SDL_assert.h"
#include "SDL_draw.h"
#include "SDL_blendfillrect.h"
@ -36,65 +37,6 @@
/* SDL surface based renderer implementation */
static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
static void SW_WindowEvent(SDL_Renderer * renderer,
const SDL_WindowEvent *event);
static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int SW_SetTextureColorMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, void **pixels, int *pitch);
static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
static int SW_UpdateViewport(SDL_Renderer * renderer);
static int SW_UpdateClipRect(SDL_Renderer * renderer);
static int SW_RenderClear(SDL_Renderer * renderer);
static int SW_RenderDrawPoints(SDL_Renderer * renderer,
const SDL_FPoint * points, int count);
static int SW_RenderDrawLines(SDL_Renderer * renderer,
const SDL_FPoint * points, int count);
static int SW_RenderFillRects(SDL_Renderer * renderer,
const SDL_FRect * rects, int count);
static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch);
static void SW_RenderPresent(SDL_Renderer * renderer);
static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static void SW_DestroyRenderer(SDL_Renderer * renderer);
SDL_RenderDriver SW_RenderDriver = {
SW_CreateRenderer,
{
"software",
SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
8,
{
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_RGBA8888,
SDL_PIXELFORMAT_BGRA8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_BGR888,
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_RGB555
},
0,
0}
};
typedef struct
{
SDL_Surface *surface;
@ -114,82 +56,11 @@ SW_ActivateRenderer(SDL_Renderer * renderer)
SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
if (surface) {
data->surface = data->window = surface;
SW_UpdateViewport(renderer);
SW_UpdateClipRect(renderer);
}
}
return data->surface;
}
SDL_Renderer *
SW_CreateRendererForSurface(SDL_Surface * surface)
{
SDL_Renderer *renderer;
SW_RenderData *data;
if (!surface) {
SDL_SetError("Can't create renderer for NULL surface");
return NULL;
}
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
SW_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
data->surface = surface;
data->window = surface;
renderer->WindowEvent = SW_WindowEvent;
renderer->GetOutputSize = SW_GetOutputSize;
renderer->CreateTexture = SW_CreateTexture;
renderer->SetTextureColorMod = SW_SetTextureColorMod;
renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
renderer->UpdateTexture = SW_UpdateTexture;
renderer->LockTexture = SW_LockTexture;
renderer->UnlockTexture = SW_UnlockTexture;
renderer->SetRenderTarget = SW_SetRenderTarget;
renderer->UpdateViewport = SW_UpdateViewport;
renderer->UpdateClipRect = SW_UpdateClipRect;
renderer->RenderClear = SW_RenderClear;
renderer->RenderDrawPoints = SW_RenderDrawPoints;
renderer->RenderDrawLines = SW_RenderDrawLines;
renderer->RenderFillRects = SW_RenderFillRects;
renderer->RenderCopy = SW_RenderCopy;
renderer->RenderCopyEx = SW_RenderCopyEx;
renderer->RenderReadPixels = SW_RenderReadPixels;
renderer->RenderPresent = SW_RenderPresent;
renderer->DestroyTexture = SW_DestroyTexture;
renderer->DestroyRenderer = SW_DestroyRenderer;
renderer->info = SW_RenderDriver.info;
renderer->driverdata = data;
SW_ActivateRenderer(renderer);
return renderer;
}
SDL_Renderer *
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_Surface *surface;
surface = SDL_GetWindowSurface(window);
if (!surface) {
return NULL;
}
return SW_CreateRendererForSurface(surface);
}
static void
SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
@ -252,46 +123,6 @@ SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
return 0;
}
static int
SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
/* If the color mod is ever enabled (non-white), permanently disable RLE (which doesn't support
* color mod) to avoid potentially frequent RLE encoding/decoding.
*/
if ((texture->r & texture->g & texture->b) != 255) {
SDL_SetSurfaceRLE(surface, 0);
}
return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
texture->b);
}
static int
SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
/* If the texture ever has multiple alpha values (surface alpha plus alpha channel), permanently
* disable RLE (which doesn't support this) to avoid potentially frequent RLE encoding/decoding.
*/
if (texture->a != 255 && surface->format->Amask) {
SDL_SetSurfaceRLE(surface, 0);
}
return SDL_SetSurfaceAlphaMod(surface, texture->a);
}
static int
SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
/* If add or mod blending are ever enabled, permanently disable RLE (which doesn't support
* them) to avoid potentially frequent RLE encoding/decoding.
*/
if ((texture->blendMode == SDL_BLENDMODE_ADD || texture->blendMode == SDL_BLENDMODE_MOD)) {
SDL_SetSurfaceRLE(surface, 0);
}
return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
}
static int
SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
@ -350,251 +181,149 @@ SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
}
static int
SW_UpdateViewport(SDL_Renderer * renderer)
SW_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
{
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
SDL_Surface *surface = data->surface;
return 0; /* nothing to do in this backend. */
}
if (!surface) {
/* We'll update the viewport after we recreate the surface */
return 0;
static int
SW_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
SDL_Point *verts = (SDL_Point *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Point), 0, &cmd->data.draw.first);
size_t i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
if (renderer->viewport.x || renderer->viewport.y) {
const int x = renderer->viewport.x;
const int y = renderer->viewport.y;
for (i = 0; i < count; i++, verts++, points++) {
verts->x = (int)(x + points->x);
verts->y = (int)(y + points->y);
}
} else {
for (i = 0; i < count; i++, verts++, points++) {
verts->x = (int)points->x;
verts->y = (int)points->y;
}
}
SDL_SetClipRect(data->surface, &renderer->viewport);
return 0;
}
static int
SW_UpdateClipRect(SDL_Renderer * renderer)
SW_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
SDL_Surface *surface = data->surface;
if (surface) {
if (renderer->clipping_enabled) {
SDL_Rect clip_rect;
clip_rect = renderer->clip_rect;
clip_rect.x += renderer->viewport.x;
clip_rect.y += renderer->viewport.y;
SDL_IntersectRect(&renderer->viewport, &clip_rect, &clip_rect);
SDL_SetClipRect(surface, &clip_rect);
} else {
SDL_SetClipRect(surface, &renderer->viewport);
SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, count * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
size_t i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
if (renderer->viewport.x || renderer->viewport.y) {
const int x = renderer->viewport.x;
const int y = renderer->viewport.y;
for (i = 0; i < count; i++, verts++, rects++) {
verts->x = (int)(x + rects->x);
verts->y = (int)(y + rects->y);
verts->w = SDL_max((int)rects->w, 1);
verts->h = SDL_max((int)rects->h, 1);
}
} else {
for (i = 0; i < count; i++, verts++, rects++) {
verts->x = (int)rects->x;
verts->y = (int)rects->y;
verts->w = SDL_max((int)rects->w, 1);
verts->h = SDL_max((int)rects->h, 1);
}
}
return 0;
}
static int
SW_RenderClear(SDL_Renderer * renderer)
SW_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
Uint32 color;
SDL_Rect clip_rect;
SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, 2 * sizeof (SDL_Rect), 0, &cmd->data.draw.first);
if (!surface) {
if (!verts) {
return -1;
}
color = SDL_MapRGBA(surface->format,
renderer->r, renderer->g, renderer->b, renderer->a);
cmd->data.draw.count = 1;
SDL_memcpy(verts, srcrect, sizeof (SDL_Rect));
verts++;
if (renderer->viewport.x || renderer->viewport.y) {
verts->x = (int)(renderer->viewport.x + dstrect->x);
verts->y = (int)(renderer->viewport.y + dstrect->y);
} else {
verts->x = (int)dstrect->x;
verts->y = (int)dstrect->y;
}
verts->w = (int)dstrect->w;
verts->h = (int)dstrect->h;
return 0;
}
typedef struct CopyExData
{
SDL_Rect srcrect;
SDL_Rect dstrect;
double angle;
SDL_FPoint center;
SDL_RendererFlip flip;
} CopyExData;
static int
SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
SDL_memcpy(&verts->srcrect, srcrect, sizeof (SDL_Rect));
if (renderer->viewport.x || renderer->viewport.y) {
verts->dstrect.x = (int)(renderer->viewport.x + dstrect->x);
verts->dstrect.y = (int)(renderer->viewport.y + dstrect->y);
} else {
verts->dstrect.x = (int)dstrect->x;
verts->dstrect.y = (int)dstrect->y;
}
verts->dstrect.w = (int)dstrect->w;
verts->dstrect.h = (int)dstrect->h;
verts->angle = angle;
SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
verts->flip = flip;
/* By definition the clear ignores the clip rect */
clip_rect = surface->clip_rect;
SDL_SetClipRect(surface, NULL);
SDL_FillRect(surface, NULL, color);
SDL_SetClipRect(surface, &clip_rect);
return 0;
}
static int
SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
int count)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
SDL_Point *final_points;
int i, status;
if (!surface) {
return -1;
}
final_points = SDL_stack_alloc(SDL_Point, count);
if (!final_points) {
return SDL_OutOfMemory();
}
if (renderer->viewport.x || renderer->viewport.y) {
int x = renderer->viewport.x;
int y = renderer->viewport.y;
for (i = 0; i < count; ++i) {
final_points[i].x = (int)(x + points[i].x);
final_points[i].y = (int)(y + points[i].y);
}
} else {
for (i = 0; i < count; ++i) {
final_points[i].x = (int)points[i].x;
final_points[i].y = (int)points[i].y;
}
}
/* Draw the points! */
if (renderer->blendMode == SDL_BLENDMODE_NONE) {
Uint32 color = SDL_MapRGBA(surface->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
status = SDL_DrawPoints(surface, final_points, count, color);
} else {
status = SDL_BlendPoints(surface, final_points, count,
renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
SDL_stack_free(final_points);
return status;
}
static int
SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
int count)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
SDL_Point *final_points;
int i, status;
if (!surface) {
return -1;
}
final_points = SDL_stack_alloc(SDL_Point, count);
if (!final_points) {
return SDL_OutOfMemory();
}
if (renderer->viewport.x || renderer->viewport.y) {
int x = renderer->viewport.x;
int y = renderer->viewport.y;
for (i = 0; i < count; ++i) {
final_points[i].x = (int)(x + points[i].x);
final_points[i].y = (int)(y + points[i].y);
}
} else {
for (i = 0; i < count; ++i) {
final_points[i].x = (int)points[i].x;
final_points[i].y = (int)points[i].y;
}
}
/* Draw the lines! */
if (renderer->blendMode == SDL_BLENDMODE_NONE) {
Uint32 color = SDL_MapRGBA(surface->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
status = SDL_DrawLines(surface, final_points, count, color);
} else {
status = SDL_BlendLines(surface, final_points, count,
renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
SDL_stack_free(final_points);
return status;
}
static int
SW_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
SDL_Rect *final_rects;
int i, status;
if (!surface) {
return -1;
}
final_rects = SDL_stack_alloc(SDL_Rect, count);
if (!final_rects) {
return SDL_OutOfMemory();
}
if (renderer->viewport.x || renderer->viewport.y) {
int x = renderer->viewport.x;
int y = renderer->viewport.y;
for (i = 0; i < count; ++i) {
final_rects[i].x = (int)(x + rects[i].x);
final_rects[i].y = (int)(y + rects[i].y);
final_rects[i].w = SDL_max((int)rects[i].w, 1);
final_rects[i].h = SDL_max((int)rects[i].h, 1);
}
} else {
for (i = 0; i < count; ++i) {
final_rects[i].x = (int)rects[i].x;
final_rects[i].y = (int)rects[i].y;
final_rects[i].w = SDL_max((int)rects[i].w, 1);
final_rects[i].h = SDL_max((int)rects[i].h, 1);
}
}
if (renderer->blendMode == SDL_BLENDMODE_NONE) {
Uint32 color = SDL_MapRGBA(surface->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
status = SDL_FillRects(surface, final_rects, count, color);
} else {
status = SDL_BlendFillRects(surface, final_rects, count,
renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
SDL_stack_free(final_rects);
return status;
}
static int
SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
SDL_Rect final_rect;
if (!surface) {
return -1;
}
if (renderer->viewport.x || renderer->viewport.y) {
final_rect.x = (int)(renderer->viewport.x + dstrect->x);
final_rect.y = (int)(renderer->viewport.y + dstrect->y);
} else {
final_rect.x = (int)dstrect->x;
final_rect.y = (int)dstrect->y;
}
final_rect.w = (int)dstrect->w;
final_rect.h = (int)dstrect->h;
if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {
return SDL_BlitSurface(src, srcrect, surface, &final_rect);
} else {
/* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
* to avoid potentially frequent RLE encoding/decoding.
*/
SDL_SetSurfaceRLE(surface, 0);
return SDL_BlitScaled(src, srcrect, surface, &final_rect);
}
}
static int
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * final_rect,
const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
SDL_Rect final_rect, tmp_rect;
SDL_Rect tmp_rect;
SDL_Surface *src_clone, *src_rotated, *src_scaled;
SDL_Surface *mask = NULL, *mask_rotated = NULL;
int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
@ -609,19 +338,10 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
return -1;
}
if (renderer->viewport.x || renderer->viewport.y) {
final_rect.x = (int)(renderer->viewport.x + dstrect->x);
final_rect.y = (int)(renderer->viewport.y + dstrect->y);
} else {
final_rect.x = (int)dstrect->x;
final_rect.y = (int)dstrect->y;
}
final_rect.w = (int)dstrect->w;
final_rect.h = (int)dstrect->h;
tmp_rect = final_rect;
tmp_rect.x = 0;
tmp_rect.y = 0;
tmp_rect.w = final_rect->w;
tmp_rect.h = final_rect->h;
/* It is possible to encounter an RLE encoded surface here and locking it is
* necessary because this code is going to access the pixel buffer directly.
@ -653,7 +373,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
}
/* If scaling and cropping is necessary, it has to be taken care of before the rotation. */
if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) {
if (!(srcrect->w == final_rect->w && srcrect->h == final_rect->h && srcrect->x == 0 && srcrect->y == 0)) {
blitRequired = SDL_TRUE;
}
@ -678,7 +398,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
* to clear the pixels in the destination surface. The other steps are explained below.
*/
if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
mask = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
if (mask == NULL) {
retval = -1;
@ -692,7 +412,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
*/
if (!retval && (blitRequired || applyModulation)) {
SDL_Rect scale_rect = tmp_rect;
src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32,
src_scaled = SDL_CreateRGBSurface(0, final_rect->w, final_rect->h, 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
if (src_scaled == NULL) {
retval = -1;
@ -723,32 +443,32 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
}
if (!retval) {
/* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
abscenterx = final_rect.x + (int)center->x;
abscentery = final_rect.y + (int)center->y;
abscenterx = final_rect->x + (int)center->x;
abscentery = final_rect->y + (int)center->y;
/* Compensate the angle inversion to match the behaviour of the other backends */
sangle = -sangle;
/* Top Left */
px = final_rect.x - abscenterx;
py = final_rect.y - abscentery;
px = final_rect->x - abscenterx;
py = final_rect->y - abscentery;
p1x = px * cangle - py * sangle + abscenterx;
p1y = px * sangle + py * cangle + abscentery;
/* Top Right */
px = final_rect.x + final_rect.w - abscenterx;
py = final_rect.y - abscentery;
px = final_rect->x + final_rect->w - abscenterx;
py = final_rect->y - abscentery;
p2x = px * cangle - py * sangle + abscenterx;
p2y = px * sangle + py * cangle + abscentery;
/* Bottom Left */
px = final_rect.x - abscenterx;
py = final_rect.y + final_rect.h - abscentery;
px = final_rect->x - abscenterx;
py = final_rect->y + final_rect->h - abscentery;
p3x = px * cangle - py * sangle + abscenterx;
p3y = px * sangle + py * cangle + abscentery;
/* Bottom Right */
px = final_rect.x + final_rect.w - abscenterx;
py = final_rect.y + final_rect.h - abscentery;
px = final_rect->x + final_rect->w - abscenterx;
py = final_rect->y + final_rect->h - abscentery;
p4x = px * cangle - py * sangle + abscenterx;
p4y = px * sangle + py * cangle + abscentery;
@ -824,6 +544,170 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
return retval;
}
static void
PrepTextureForCopy(const SDL_RenderCommand *cmd)
{
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const SDL_BlendMode blend = cmd->data.draw.blend;
SDL_Texture *texture = cmd->data.draw.texture;
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
SDL_SetSurfaceRLE(surface, 0);
SDL_SetSurfaceColorMod(surface, r, g, b);
}
if ((texture->modMode & SDL_TEXTUREMODULATE_ALPHA) && surface->format->Amask) {
SDL_SetSurfaceRLE(surface, 0);
SDL_SetSurfaceAlphaMod(surface, a);
}
if ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD)) {
SDL_SetSurfaceRLE(surface, 0);
}
SDL_SetSurfaceBlendMode(surface, blend);
}
static int
SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
SDL_Surface *surface = SW_ActivateRenderer(renderer);
const SDL_Rect *viewport = NULL;
const SDL_Rect *cliprect = NULL;
if (!surface) {
return -1;
}
while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR: {
break; /* Not used in this backend. */
}
case SDL_RENDERCMD_SETVIEWPORT: {
viewport = &cmd->data.viewport.rect;
SDL_SetClipRect(data->surface, viewport);
break;
}
case SDL_RENDERCMD_SETCLIPRECT: {
SDL_assert(viewport != NULL);
cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
if (cliprect) {
SDL_Rect clip_rect = { cliprect->x + viewport->x, cliprect->y + viewport->y, cliprect->w, cliprect->h };
SDL_IntersectRect(viewport, &clip_rect, &clip_rect);
SDL_SetClipRect(surface, &clip_rect);
} else {
SDL_SetClipRect(surface, viewport);
}
break;
}
case SDL_RENDERCMD_CLEAR: {
const Uint8 r = cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const SDL_Rect clip_rect = surface->clip_rect;
/* By definition the clear ignores the clip rect */
SDL_SetClipRect(surface, NULL);
SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, r, g, b, a));
SDL_SetClipRect(surface, &clip_rect);
break;
}
case SDL_RENDERCMD_DRAW_POINTS: {
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const size_t count = cmd->data.draw.count;
const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
const SDL_BlendMode blend = cmd->data.draw.blend;
if (blend == SDL_BLENDMODE_NONE) {
SDL_DrawPoints(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
} else {
SDL_BlendPoints(surface, verts, count, blend, r, g, b, a);
}
break;
}
case SDL_RENDERCMD_DRAW_LINES: {
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const size_t count = cmd->data.draw.count;
const SDL_Point *verts = (SDL_Point *) (((Uint8 *) vertices) + cmd->data.draw.first);
const SDL_BlendMode blend = cmd->data.draw.blend;
if (blend == SDL_BLENDMODE_NONE) {
SDL_DrawLines(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
} else {
SDL_BlendLines(surface, verts, count, blend, r, g, b, a);
}
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const size_t count = cmd->data.draw.count;
const SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
const SDL_BlendMode blend = cmd->data.draw.blend;
if (blend == SDL_BLENDMODE_NONE) {
SDL_FillRects(surface, verts, count, SDL_MapRGBA(surface->format, r, g, b, a));
} else {
SDL_BlendFillRects(surface, verts, count, blend, r, g, b, a);
}
break;
}
case SDL_RENDERCMD_COPY: {
SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
const SDL_Rect *srcrect = verts;
SDL_Rect *dstrect = verts + 1;
SDL_Texture *texture = cmd->data.draw.texture;
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
PrepTextureForCopy(cmd);
if ( srcrect->w == dstrect->w && srcrect->h == dstrect->h ) {
SDL_BlitSurface(src, srcrect, surface, dstrect);
} else {
/* If scaling is ever done, permanently disable RLE (which doesn't support scaling)
* to avoid potentially frequent RLE encoding/decoding.
*/
SDL_SetSurfaceRLE(surface, 0);
SDL_BlitScaled(src, srcrect, surface, dstrect);
}
break;
}
case SDL_RENDERCMD_COPY_EX: {
const CopyExData *copydata = (CopyExData *) (((Uint8 *) vertices) + cmd->data.draw.first);
PrepTextureForCopy(cmd);
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
&copydata->dstrect, copydata->angle, &copydata->center, copydata->flip);
break;
}
case SDL_RENDERCMD_NO_OP:
break;
}
cmd = cmd->next;
}
return 0;
}
static int
SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
@ -882,6 +766,91 @@ SW_DestroyRenderer(SDL_Renderer * renderer)
SDL_free(renderer);
}
SDL_Renderer *
SW_CreateRendererForSurface(SDL_Surface * surface)
{
SDL_Renderer *renderer;
SW_RenderData *data;
if (!surface) {
SDL_SetError("Can't create renderer for NULL surface");
return NULL;
}
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
SW_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
data->surface = surface;
data->window = surface;
renderer->WindowEvent = SW_WindowEvent;
renderer->GetOutputSize = SW_GetOutputSize;
renderer->CreateTexture = SW_CreateTexture;
renderer->UpdateTexture = SW_UpdateTexture;
renderer->LockTexture = SW_LockTexture;
renderer->UnlockTexture = SW_UnlockTexture;
renderer->SetRenderTarget = SW_SetRenderTarget;
renderer->QueueSetViewport = SW_QueueSetViewport;
renderer->QueueSetDrawColor = SW_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = SW_QueueDrawPoints;
renderer->QueueDrawLines = SW_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueFillRects = SW_QueueFillRects;
renderer->QueueCopy = SW_QueueCopy;
renderer->QueueCopyEx = SW_QueueCopyEx;
renderer->RunCommandQueue = SW_RunCommandQueue;
renderer->RenderReadPixels = SW_RenderReadPixels;
renderer->RenderPresent = SW_RenderPresent;
renderer->DestroyTexture = SW_DestroyTexture;
renderer->DestroyRenderer = SW_DestroyRenderer;
renderer->info = SW_RenderDriver.info;
renderer->driverdata = data;
SW_ActivateRenderer(renderer);
return renderer;
}
SDL_Renderer *
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_Surface *surface;
surface = SDL_GetWindowSurface(window);
if (!surface) {
return NULL;
}
return SW_CreateRendererForSurface(surface);
}
SDL_RenderDriver SW_RenderDriver = {
SW_CreateRenderer,
{
"software",
SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
8,
{
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_RGBA8888,
SDL_PIXELFORMAT_BGRA8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_BGR888,
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_RGB555
},
0,
0}
};
#endif /* !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -187,6 +187,7 @@ Cocoa_InitModes(_THIS)
CGDisplayErr result;
CGDirectDisplayID *displays;
CGDisplayCount numDisplays;
SDL_bool isstack;
int pass, i;
result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
@ -194,11 +195,11 @@ Cocoa_InitModes(_THIS)
CG_SetError("CGGetOnlineDisplayList()", result);
return;
}
displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
displays = SDL_small_alloc(CGDirectDisplayID, numDisplays, &isstack);
result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
if (result != kCGErrorSuccess) {
CG_SetError("CGGetOnlineDisplayList()", result);
SDL_stack_free(displays);
SDL_small_free(displays, isstack);
return;
}
@ -260,7 +261,7 @@ Cocoa_InitModes(_THIS)
SDL_free(display.name);
}
}
SDL_stack_free(displays);
SDL_small_free(displays, isstack);
}}
int

View file

@ -47,6 +47,7 @@
#include "xdg-shell-client-protocol.h"
#include "xdg-shell-unstable-v6-client-protocol.h"
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
#define WAYLANDVID_DRIVER_NAME "wayland"
@ -182,6 +183,7 @@ Wayland_CreateDevice(int devindex)
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
device->MaximizeWindow = Wayland_MaximizeWindow;
device->RestoreWindow = Wayland_RestoreWindow;
device->SetWindowBordered = Wayland_SetWindowBordered;
device->SetWindowSize = Wayland_SetWindowSize;
device->SetWindowTitle = Wayland_SetWindowTitle;
device->DestroyWindow = Wayland_DestroyWindow;
@ -345,6 +347,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
{
SDL_VideoData *d = data;
/*printf("WAYLAND INTERFACE: %s\n", interface);*/
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor = wl_registry_bind(d->registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "wl_output") == 0) {
@ -368,6 +372,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
Wayland_display_add_pointer_constraints(d, id);
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, 3);
} else if (strcmp(interface, "org_kde_kwin_server_decoration_manager") == 0) {
d->kwin_server_decoration_manager = wl_registry_bind(d->registry, id, &org_kde_kwin_server_decoration_manager_interface, 1);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (strcmp(interface, "qt_touch_extension") == 0) {

View file

@ -61,6 +61,7 @@ typedef struct {
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
struct wl_data_device_manager *data_device_manager;
struct org_kde_kwin_server_decoration_manager *kwin_server_decoration_manager;
EGLDisplay edpy;
EGLContext context;

View file

@ -35,6 +35,7 @@
#include "xdg-shell-client-protocol.h"
#include "xdg-shell-unstable-v6-client-protocol.h"
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
/* On modern desktops, we probably will use the xdg-shell protocol instead
of wl_shell, but wl_shell might be useful on older Wayland installs that
@ -451,6 +452,17 @@ Wayland_RestoreWindow(_THIS, SDL_Window * window)
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
}
void
Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{
SDL_WindowData *wind = window->driverdata;
const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
if ((viddata->kwin_server_decoration_manager) && (wind->kwin_server_decoration)) {
const enum org_kde_kwin_server_decoration_mode mode = bordered ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER : ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE;
org_kde_kwin_server_decoration_request_mode(wind->kwin_server_decoration, mode);
}
}
void
Wayland_MaximizeWindow(_THIS, SDL_Window * window)
{
@ -562,6 +574,15 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
if (c->kwin_server_decoration_manager) {
data->kwin_server_decoration = org_kde_kwin_server_decoration_manager_create(c->kwin_server_decoration_manager, data->surface);
if (data->kwin_server_decoration) {
const SDL_bool bordered = (window->flags & SDL_WINDOW_BORDERLESS) == 0;
const enum org_kde_kwin_server_decoration_mode mode = bordered ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER : ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE;
org_kde_kwin_server_decoration_request_mode(data->kwin_server_decoration, mode);
}
}
region = wl_compositor_create_region(c->compositor);
wl_region_add(region, 0, 0, window->w, window->h);
wl_surface_set_opaque_region(data->surface, region);
@ -636,6 +657,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
SDL_EGL_DestroySurface(_this, wind->egl_surface);
WAYLAND_wl_egl_window_destroy(wind->egl_window);
if (wind->kwin_server_decoration) {
org_kde_kwin_server_decoration_release(wind->kwin_server_decoration);
}
if (data->shell.xdg) {
if (wind->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);

View file

@ -62,6 +62,7 @@ typedef struct {
struct SDL_WaylandInput *keyboard_device;
EGLSurface egl_surface;
struct zwp_locked_pointer_v1 *locked_pointer;
struct org_kde_kwin_server_decoration *kwin_server_decoration;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct qt_extended_surface *extended_surface;
@ -74,6 +75,7 @@ extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_bool fullscreen);
extern void Wayland_MaximizeWindow(_THIS, SDL_Window * window);
extern void Wayland_RestoreWindow(_THIS, SDL_Window * window);
extern void Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowSize(_THIS, SDL_Window * window);
extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);

View file

@ -908,7 +908,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_TOUCH:
if (data->videodata->GetTouchInputInfo && data->videodata->CloseTouchInputHandle) {
UINT i, num_inputs = LOWORD(wParam);
PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
SDL_bool isstack;
PTOUCHINPUT inputs = SDL_small_alloc(TOUCHINPUT, num_inputs, &isstack);
if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
RECT rect;
float x, y;
@ -916,7 +917,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (!GetClientRect(hwnd, &rect) ||
(rect.right == rect.left && rect.bottom == rect.top)) {
if (inputs) {
SDL_stack_free(inputs);
SDL_small_free(inputs, isstack);
}
break;
}
@ -950,7 +951,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
}
}
SDL_stack_free(inputs);
SDL_small_free(inputs, isstack);
data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
return 0;
@ -961,17 +962,19 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
UINT i;
HDROP drop = (HDROP) wParam;
SDL_bool isstack;
UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
for (i = 0; i < count; ++i) {
SDL_bool isstack;
UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
LPTSTR buffer = SDL_small_alloc(TCHAR, size, &isstack);
if (buffer) {
if (DragQueryFile(drop, i, buffer, size)) {
char *file = WIN_StringToUTF8(buffer);
SDL_SendDropFile(data->window, file);
SDL_free(file);
}
SDL_stack_free(buffer);
SDL_small_free(buffer, isstack);
}
}
SDL_SendDropComplete(data->window);

View file

@ -27,6 +27,7 @@
int WIN_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_bool isstack;
size_t size;
LPBITMAPINFO info;
HBITMAP hbm;
@ -41,7 +42,7 @@ int WIN_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, voi
/* Find out the format of the screen */
size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
info = (LPBITMAPINFO)SDL_stack_alloc(Uint8, size);
info = (LPBITMAPINFO)SDL_small_alloc(Uint8, size, &isstack);
if (!info) {
return SDL_OutOfMemory();
}
@ -85,7 +86,7 @@ int WIN_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, voi
data->mdc = CreateCompatibleDC(data->hdc);
data->hbm = CreateDIBSection(data->hdc, info, DIB_RGB_COLORS, pixels, NULL, 0);
SDL_stack_free(info);
SDL_small_free(info, isstack);
if (!data->hbm) {
return WIN_SetError("Unable to create DIB");

View file

@ -97,6 +97,7 @@ WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
LPVOID pixels;
LPVOID maskbits;
size_t maskbitslen;
SDL_bool isstack;
ICONINFO ii;
SDL_zero(bmh);
@ -112,7 +113,7 @@ WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
bmh.bV4BlueMask = 0x000000FF;
maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h;
maskbits = SDL_stack_alloc(Uint8,maskbitslen);
maskbits = SDL_small_alloc(Uint8,maskbitslen);
if (maskbits == NULL) {
SDL_OutOfMemory();
return NULL;
@ -129,7 +130,7 @@ WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0);
ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits);
ReleaseDC(NULL, hdc);
SDL_stack_free(maskbits);
SDL_small_free(maskbits, isstack);
SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
SDL_assert(surface->pitch == surface->w * 4);

View file

@ -380,10 +380,11 @@ WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
HWND hwnd = (HWND) data;
LPTSTR title;
int titleLen;
SDL_bool isstack;
/* Query the title from the existing window */
titleLen = GetWindowTextLength(hwnd);
title = SDL_stack_alloc(TCHAR, titleLen + 1);
title = SDL_small_alloc(TCHAR, titleLen + 1, &isstack);
if (title) {
titleLen = GetWindowText(hwnd, title, titleLen);
} else {
@ -393,7 +394,7 @@ WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
window->title = WIN_StringToUTF8(title);
}
if (title) {
SDL_stack_free(title);
SDL_small_free(title, isstack);
}
if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
@ -443,14 +444,15 @@ WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
BYTE *icon_bmp;
int icon_len, mask_len, y;
SDL_RWops *dst;
SDL_bool isstack;
/* Create temporary buffer for ICONIMAGE structure */
mask_len = (icon->h * (icon->w + 7)/8);
icon_len = 40 + icon->h * icon->w * sizeof(Uint32) + mask_len;
icon_bmp = SDL_stack_alloc(BYTE, icon_len);
icon_bmp = SDL_small_alloc(BYTE, icon_len, &isstack);
dst = SDL_RWFromMem(icon_bmp, icon_len);
if (!dst) {
SDL_stack_free(icon_bmp);
SDL_small_free(icon_bmp, isstack);
return;
}
@ -481,7 +483,7 @@ WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
SDL_RWclose(dst);
SDL_stack_free(icon_bmp);
SDL_small_free(icon_bmp, isstack);
/* Set the icon for the window */
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);

View file

@ -37,6 +37,8 @@ static SDL_Rect *positions;
static SDL_Rect *velocities;
static int sprite_w, sprite_h;
static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND;
static Uint32 next_fps_check, frames;
static const Uint32 fps_check_delay = 5000;
/* Number of iterations to move sprites - used for visual tests. */
/* -1: infinite random moves (default); >=0: enables N deterministic moves */
@ -244,6 +246,7 @@ MoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
void
loop()
{
Uint32 now;
int i;
SDL_Event event;
@ -261,13 +264,24 @@ loop()
emscripten_cancel_main_loop();
}
#endif
frames++;
now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, next_fps_check)) {
/* Print out some timing information */
const Uint32 then = next_fps_check - fps_check_delay;
const double fps = ((double) frames * 1000) / (now - then);
SDL_Log("%2.2f frames per second\n", fps);
next_fps_check = now + fps_check_delay;
frames = 0;
}
}
int
main(int argc, char *argv[])
{
int i;
Uint32 then, now, frames;
Uint64 seed;
const char *icon = "icon.bmp";
@ -384,24 +398,17 @@ main(int argc, char *argv[])
/* Main render loop */
frames = 0;
then = SDL_GetTicks();
next_fps_check = SDL_GetTicks() + fps_check_delay;
done = 0;
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(loop, 0, 1);
#else
while (!done) {
++frames;
loop();
}
#endif
/* Print out some timing information */
now = SDL_GetTicks();
if (now > then) {
double fps = ((double) frames * 1000) / (now - then);
SDL_Log("%2.2f frames per second\n", fps);
}
quit(0);
return 0;
}

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="server_decoration">
<copyright><![CDATA[
Copyright (C) 2015 Martin Gräßlin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]></copyright>
<interface name="org_kde_kwin_server_decoration_manager" version="1">
<description summary="Server side window decoration manager">
This interface allows to coordinate whether the server should create
a server-side window decoration around a wl_surface representing a
shell surface (wl_shell_surface or similar). By announcing support
for this interface the server indicates that it supports server
side decorations.
</description>
<request name="create">
<description summary="Create a server-side decoration object for a given surface">
When a client creates a server-side decoration object it indicates
that it supports the protocol. The client is supposed to tell the
server whether it wants server-side decorations or will provide
client-side decorations.
If the client does not create a server-side decoration object for
a surface the server interprets this as lack of support for this
protocol and considers it as client-side decorated. Nevertheless a
client-side decorated surface should use this protocol to indicate
to the server that it does not want a server-side deco.
</description>
<arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
<enum name="mode">
<description summary="Possible values to use in request_mode and the event mode."/>
<entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/>
<entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
<entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
</enum>
<event name="default_mode">
<description summary="The default mode used on the server">
This event is emitted directly after binding the interface. It contains
the default mode for the decoration. When a new server decoration object
is created this new object will be in the default mode until the first
request_mode is requested.
The server may change the default mode at any time.
</description>
<arg name="mode" type="uint" summary="The default decoration mode applied to newly created server decorations."/>
</event>
</interface>
<interface name="org_kde_kwin_server_decoration" version="1">
<request name="release" type="destructor">
<description summary="release the server decoration object"/>
</request>
<enum name="mode">
<description summary="Possible values to use in request_mode and the event mode."/>
<entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/>
<entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
<entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
</enum>
<request name="request_mode">
<description summary="The decoration mode the surface wants to use."/>
<arg name="mode" type="uint" summary="The mode this surface wants to use."/>
</request>
<event name="mode">
<description summary="The new decoration mode applied by the server">
This event is emitted directly after the decoration is created and
represents the base decoration policy by the server. E.g. a server
which wants all surfaces to be client-side decorated will send Client,
a server which wants server-side decoration will send Server.
The client can request a different mode through the decoration request.
The server will acknowledge this by another event with the same mode. So
even if a server prefers server-side decoration it's possible to force a
client-side decoration.
The server may emit this event at any time. In this case the client can
again request a different mode. It's the responsibility of the server to
prevent a feedback loop.
</description>
<arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/>
</event>
</interface>
</protocol>