Patch for sub surfaces

All the talk of implementing multiple windows got me thinking again
about a feature of SDL I always thought would be cool - the ability to
create surfaces which were really just sub-rectangles of other surfaces.
Great for split-screen multiplayer support!

I think allegro has this feature - at least it did 10 years ago when I
was using it on DOS, and I really liked it. Seemed lovely and elegant.

Anyway, I’ve attached a patch (against the latest from CVS) and a noddy
little demo program.

The patch implements an extra surface flag (SDL_SUBSURFACE), three extra
fields in SDL_Surface (uhoh!), and a new API call: SDL_CreateSubSurface().

I think it maintains binary compatibility. As long as apps use SDL to
allocate and free surfaces, then the extra fields on SDL_Surface
shouldn’t be a problem. And even if an app does alloc it’s own
SDL_Surface structs on the heap or stack, SDL wouldn’t ever attempt to
read the (missing) extra fields unless the SDL_SUBSURFACE flag is set…
(actually I think my patch might need a slight tweak to ensure this).
I don’t think adding a new API call to the library breaks binary
compatibility, but I could be wrong about that…

Anyway, I don’t have any particular vested interest in this feature (not
doing any split-screen games at the moment :-). I just thought it’d be
fun to implement, so I’m not too worried or offended if it falls in the
bit bucket.
But hopefully someone might find it useful!

docs for the new API call:----------------------------------------------------
Synopsis:

SDL_Surface *SDL_CreateSubSurface( SDL_Surface *parent, const SDL_Rect
*area );

Description:

Creates a surface which is really just an sub-area of a parent surface.
The subsurface is like a window on to the parent. Drawing to the subsurface
draws directly to the parent.

If a parent surface is the screen, then the subsurface can also be
treated as
a screen. That is, SDL_UpdateRect() SDL_UpdateRects() should work as
expected
on a subsurface of the screen (internally, the rectangles will be mapped to
the screen).

Subsurfaces have the internal flags SDL_SUBSURFACE and SDL_PREALLOC set.
Relevant fields in SDL_Surface:
parent: points to the parent surface
parent_x: x position of subsurface on the parent
parent_y: y position of subsurface on the parent

Ben.

http://www.scumways.com

-------------- next part --------------
A non-text attachment was scrubbed…
Name: subsurface.patch
Type: text/x-patch
Size: 5389 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20050622/5e62b9f5/attachment.bin
-------------- next part --------------
A non-text attachment was scrubbed…
Name: subsurfacetest.c
Type: text/x-csrc
Size: 1410 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20050622/5e62b9f5/attachment.c

All the talk of implementing multiple windows got me thinking again
about a feature of SDL I always thought would be cool - the ability to
create surfaces which were really just sub-rectangles of other surfaces.
Great for split-screen multiplayer support!

I’ve been using sub-surfaces for ages with plain SDL… I just use
SDL_CreateRGBSurfaceFrom() using a pointer to the parent surface data. I
haven’t found a single problem… does your patch address any
shortcoming I’m not aware of?

    --Gabriel

I’ve been using sub-surfaces for ages with plain SDL… I just use
SDL_CreateRGBSurfaceFrom() using a pointer to the parent surface data. I
haven’t found a single problem… does your patch address any
shortcoming I’m not aware of?

It doesn’t accomplish anything that you can’t already do with SDL’s
clipping rectangles, but it does make the subsurface look like it starts
at coordinates (0,0), which can simplify some app logic.

I don’t know that it makes it something to add to the API, but it’s nice
that the patch is out there for people that need it.

–ryan.

El mi?, 22-06-2005 a las 20:31 -0400, Ryan C. Gordon escribi?:

I’ve been using sub-surfaces for ages with plain SDL… I just use
SDL_CreateRGBSurfaceFrom() using a pointer to the parent surface data. I
haven’t found a single problem… does your patch address any
shortcoming I’m not aware of?

It doesn’t accomplish anything that you can’t already do with SDL’s
clipping rectangles, but it does make the subsurface look like it starts
at coordinates (0,0), which can simplify some app logic.

I’m not sure I understand what you mean… without the patch, and with
just SDL_CreateRGBSurfaceFrom(), I can use sub-surfaces that start at
(0,0).

Gabriel wrote:

El mi?, 22-06-2005 a las 20:31 -0400, Ryan C. Gordon escribi?:

I’ve been using sub-surfaces for ages with plain SDL… I just use
SDL_CreateRGBSurfaceFrom() using a pointer to the parent surface data. I
haven’t found a single problem… does your patch address any
shortcoming I’m not aware of?

It doesn’t accomplish anything that you can’t already do with SDL’s
clipping rectangles, but it does make the subsurface look like it starts
at coordinates (0,0), which can simplify some app logic.

I’m not sure I understand what you mean… without the patch, and with
just SDL_CreateRGBSurfaceFrom(), I can use sub-surfaces that start at
(0,0).

It means you can create subsurfaces which start at some offset within a
larger parent surface, and can have a smaller width and height. With
CreateRGBSurfaceFrom(), the new surface addresses the entire area of the
parent.
Also, if the parent is the screen, you can treat the subsurface as if it
were a screen, and call the updaterect functions on it.

Like Ryan said, it’s nothing that can’t be achieved with clipping
rectangles and offsets. But I like the idea that you can set up multiple
viewports, and use the exact same drawing code for each one. The drawing
code can assume it’s got the whole screen to itself.

Ben.

I’m not sure I understand what you mean… without the patch, and with
just SDL_CreateRGBSurfaceFrom(), I can use sub-surfaces that start at
(0,0).

Yes, but it’s a whole seperate block of memory that takes up seperate
resources and would need to be blitted back to the original surface if
you wanted to update the original.

–ryan.

If it’s not in the API, people can’t really use it without custom-building
their own SDL; which isn’t a barrier for you, but rules out lots of
developers and all commercial SDL programmers. Some of it could be done
with a library, but not all of it, especially not the intelligent reference
counting.

Could it at least be considered for SDL 1.3? Seldom have I seen an addition
so simple and elegant.On June 22, 2005 06:31 pm, Ryan C. Gordon wrote:

It doesn’t accomplish anything that you can’t already do with SDL’s
clipping rectangles, but it does make the subsurface look like it starts
at coordinates (0,0), which can simplify some app logic.

I don’t know that it makes it something to add to the API, but it’s nice
that the patch is out there for people that need it.

Quoth “Ryan C. Gordon” , on 2005-06-23 10:39:19 -0400:

Yes, but it’s a whole seperate block of memory that takes up seperate
resources and would need to be blitted back to the original surface if
you wanted to update the original.

Firstly, from the manpage of SDL_CreateRGBSurfaceFrom:

The data stored in pixels is assumed to be of the depth specified in
the parameter list.  The pixel data is not copied into the SDL_Surface
structure so it should not be freed until the surface has been freed
with a called to SDL_FreeSurface. pitch is the length of each scanline
in bytes.

Secondly, wasn’t the reference to SDL_CreateRGBSurfaceFrom a reference
to using different widths, heights, pitches, and offsets into the
original pixels array to create displaced subsurfaces that act like
they’re ordinay surfaces but just happen to share the same block of
memory?

Perhaps I’m just misunderstanding something…

—> Drake Wilson

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20050623/5b6dcca9/attachment.pgp

Could it at least be considered for SDL 1.3? Seldom have I seen an addition
so simple and elegant.

Well, obviously this is Sam’s call…I didn’t mean to sound like the
authority here.

–ryan.

El jue, 23-06-2005 a las 07:57 +0000, Ben Campbell escribi?:

It means you can create subsurfaces which start at some offset within a
larger parent surface, and can have a smaller width and height. With
CreateRGBSurfaceFrom(), the new surface addresses the entire area of the
parent.

El jue, 23-06-2005 a las 10:39 -0400, Ryan C. Gordon escribi?:

Yes, but it’s a whole seperate block of memory that takes up seperate
resources and would need to be blitted back to the original surface if
you wanted to update the original.

No, no, believe me, I use SDL_CreateRGBSurfaceFrom() to create surfaces
that a) start at any offset within the parent surface, b) have any width
and height (that fits inside the parent, of course), c) share memory
with the parent… here’s the code :-----
(the parameters are pParent, nTop, nLeft, nWidth, nHeight)

SDL_LockSurface(pParent);

byte* pPixels = (byte*)pParent->pixels + pParent->pitch*nTop + pParent-

format->BytesPerPixel * nLeft;

m_pSurface = SDL_CreateRGBSurfaceFrom(pPixels, nWidth, nHeight, pParent-

format->BitsPerPixel, pParent->pitch, pParent->format->Rmask, pParent-
format->Gmask, pParent->format->Bmask, pParent->format->Amask);

if (pParent->format->palette)
SDL_SetColors(m_pSurface, pParent->format->palette->colors, 0, pParent-

format->palette->ncolors);

SDL_UnlockSurface(pParent);

Drake Wilson wrote:

Secondly, wasn’t the reference to SDL_CreateRGBSurfaceFrom a reference
to using different widths, heights, pitches, and offsets into the
original pixels array to create displaced subsurfaces that act like
they’re ordinay surfaces but just happen to share the same block of
memory?

I hadn’t really thought of using CreateRGBSurfaceFrom() like that, but
yeah I think you’re right.
The benefits of my patch are:

  1. more obvious interface (caller doesn’t need to calculate the pixel
    address, or pass in bitmasks)
  2. you can call SDL_UpdateRect[s] directly on a subsurface of the
    screen, whereas with CreateRGBSurfaceFrom() you have to map the
    rectangles back onto the screen yourself.
  3. the subsurface stores it’s xy offset relative to the parent (in the
    new parent_x and parent_y fields) which is handy when, say, mapping
    mouse event positions from the screen to the subsurface. Minor benefit,
    but means the app doesn’t have to keep track of that kind of thing
    itself - all the info you need is in the surface.

Ben.

No, no, believe me, I use SDL_CreateRGBSurfaceFrom() to create surfaces
that a) start at any offset within the parent surface, b) have any width
and height (that fits inside the parent, of course), c) share memory
with the parent… here’s the code :

Oh, I see what you’re saying. Just a note:

SDL_UnlockSurface(pParent);

The subsurface’s pixel data might be gone when you unlock the parent’s
surface. This will work if you guarantee that SDL_MUSTLOCK(pParent) is
false (i.e. - it’s never a hardware surface)…but having to lock a
surface means you’re temporarily copying it to memory for byte-level
manipulation and ditching that memory block after the unlock is complete.

Without heavy examination of the Subsurface patch, I assume they’ll have
the same issue, or they just fail to create if the parent has the
SDL_HWSURFACE flag.

–ryan.

Secondly, wasn’t the reference to SDL_CreateRGBSurfaceFrom a reference
to using different widths, heights, pitches, and offsets into the
original pixels array to create displaced subsurfaces that act like
they’re ordinay surfaces but just happen to share the same block of
memory?

I just figured it was for creating a surface when you’ve already
allocated a memory buffer yourself (say, because some image library
decompressed to a memory buffer and then you later want to create a
surface around it).

Perhaps I’m just misunderstanding something…

I misread the first mail. Most of the confusion is my fault. :slight_smile:

–ryan.

Ryan C. Gordon wrote:

Oh, I see what you’re saying. Just a note:

SDL_UnlockSurface(pParent);

The subsurface’s pixel data might be gone when you unlock the parent’s
surface. This will work if you guarantee that SDL_MUSTLOCK(pParent) is
false (i.e. - it’s never a hardware surface)…but having to lock a
surface means you’re temporarily copying it to memory for byte-level
manipulation and ditching that memory block after the unlock is complete.

Without heavy examination of the Subsurface patch, I assume they’ll have
the same issue, or they just fail to create if the parent has the
SDL_HWSURFACE flag.

I think you’re right. My patch does increment the refcount of the parent
surface, but I guess refers only to the surface struct itself and not
the pixeldata.

Ben.

El jue, 23-06-2005 a las 15:12 -0400, Ryan C. Gordon escribi?:

SDL_UnlockSurface(pParent);

The subsurface’s pixel data might be gone when you unlock the parent’s
surface. This will work if you guarantee that SDL_MUSTLOCK(pParent) is
false (i.e. - it’s never a hardware surface)…

You’re right. I guess it works in my case because I don’t use hardware
surfaces. And I do the refcount management on a higher level (ie a
parent is never deallocated before its children)

    --Gabriel

Could it at least be considered for SDL 1.3? Seldom have I seen an addition
so simple and elegant.

Well, obviously this is Sam’s call…I didn’t mean to sound like the
authority here.

Ya’know… I personally would object to this one just because of the
questions it would generate on the mailing list. How many times are we
going to see questions about using sub-sufaces in OpenGL and so on. Not
to mention how easy it is to do with clipping rectangles and the create
surface from hack…

Ok, I know I am being a curmudgeon, but some features create more
problems than they are worth.

	Bob PendletonOn Thu, 2005-06-23 at 13:31 -0400, Ryan C. Gordon wrote:

–ryan.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


±-------------------------------------+