![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
Hi everyone, I'm Petruza, I'm posting for the first time in this list.
I'm coding an emulator and want to load the tiles into tile_sheet which is an SDL_Surface. To make rect blitting easier, I thought of making the tile_sheet of 256 x 8 pixels. Is it more or less efficient than making a more square-ish surface? Since I'm not using the whole surface, but just 8x8 rects out of it, the dimensions really don't matter, so I'm free to make them anything I want having efficiency in mind. Also, what does the pitch depend on, besides surface width? it depends on the video hardware? Can I assume that a surface which is not wider than the main SDL screen surface (SDL 1.2) will have the same pitch as the screen? Thanks PS: I signed-up on the SDL forums but I'm not granted permission to post or reply, and private messages are disabled so I can't contact any admin. Do you know why is this? _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Bob
![]() |
![]() |
On Sat, May 22, 2010 at 10:13 AM, Ernesto Borio
wrote:
Look, the word "efficiency" usually does not mean what people think it means. I am not trying to be an ass hole, I'm just an old programmer (57 years old, programming since I was 19) who has come to learn that any time someone is worrying about efficiency and they have not characterized the problem in terms of an algorithm they are in danger of chasing off down the rabbit hole. When they start talking about efficiency and they are worrying about trying to save what amounts to less than 1 percent of a resource, be it time, memory, disk space, or what ever, and are not worried about wasting the one resource that only gets more expensive every day, which is the time left in their life, then they are already deep into the rabbit whole and may have already been sipping on the bottle of drink me that warps the minds of so many programmers. So, remembering that I am trying to keep you from wasting any part of your life chasing rabbits please read the following: How many tiles are you going to have? What size are the pixels? When you say 8x8 what are the units you are using for the number? Is it pixels, bytes, inches? It is hard to answer a question when you leave most of the information in your head :-) Ok, so if I assume that 8x8 is in pixels, which by the way is very very small on a modern screen then each tile is 64 pixels. If I assume that each pixel is 32 bits/4 bytes, then a tile is 256 bytes. That means at the best possible packing you get 4 tiles per kilobyte or 4 kilotiles per megabyte. But, you said you are writing an emulator so you are mostly likely emulating some ancient video game system or computer which probably only support a few dozen tiles. Of course, this is another assumption because you didn't mention what you were doing. To me that means that you are going to use up a fraction of one percent of the memory on your computer or your graphics card for storing these tiles. So, why are you worrying about the "efficiency" of this storage? Just do it how ever works out best for your project and stop spending time on problems that are not problems? :-) OTOH, if you really want to make it fast and don't care about using a little bit of memory you might want to just make the tiles into OpenGL textures so they are stored in the video card memory where the graphics hardware can get at them and slam them around the screen so fast no display can keep up. Plus, OpenGL solves about 2000 of the next 10 problems you are going to run into. Do not optimize your code until you have evidence that it is too slow. Write the simplest code you can as quickly as you can because in a project like yours you are likely to have to rewrite it several times. If you have already invested a lot of work into getting it "optimized" you will be unwilling to throw away all that work and you will waste a lot more time trying to keep it optimized. That means you may wind up optimizing the same code dozens of times. On the other hand, if you make it simple and easy to code and only optimize it when the projects works, but is too slow. You will only optimize it once. And, if you use a profiler to find the slow spots you might find that only two or three sections of code need to be optimized. But, more importantly, you may find that the optimization requires changes of a more global natures that you could never guess at during the early stages of development. Never optimize code until testing shows you that the application is too slow. Only optimize code after a profiler shows you that it must be optimized. In your current problem the only thing you need to worry about is making sure that the SDL_Surface you wind up with is properly laid out to work with the graphics system you are rendering on. You really do not want to be converting from say and 8 bit image to a 32 bit image before each blit. Ok, back on the subject of really helping you, please give us more information about what you are trying to accomplish, not about a specific problem that is occupying your mind right now. Bob Pendleton
-- +----------------------------------------------------------- + Bob Pendleton: writer and programmer + email: + web: www.TheGrumpyProgrammer.com _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
Thanks Bob for the huge answer, I'm not concerned about asshole replies, everything that someone has to tell me that can teach me something I don't know, is appreciated.
( Note: in my previous message I wrote "256x8 pixels", I really meant 512 x 1 tiles, I.E. 4096x8 pixels ) I'm developing a NES* emulator, tiles are 8x8 pixels, in the particular implementation I'm working on, there are 512 tiles arranged in a linear Tile ROM. I'm reading the tile data and storing it in an `Uint32 array[512]` in XRGB format. So blitting will be always 32bpp to 32bpp, no mapping or transformation whatsoever. What I'm gonna do is blit a specific 8x8 rect from the tile sheet to the screen in the place that specific tile should be placed. I read before some advices like yours about not spending resources (mainly man-hours) optimizing something I don't know needs optimization in the first place. And that optimization should take place once you spot a bottleneck that's worth putting some time on to resolve it. But my question more than optimization is, as I won't be blitting the tile sheet completely, but will blit individual tiles, I.E. 8x8 rects, it's the same to me to implement the tile sheet (which I haven't yet so it won't be optimization, it will just be first time implementation) as: 1) a 512 x 1 tiles surface 2) a 1 x 512 tiles surface 3) a 32 x 16 tiles surface or any other dimension that is better for SDL for any reason I don't yet know. I know any of this choices will perform almost the same but as the effort needed to implement either is relatively the same, I can choose any of them. For example, I guess that making the tile sheet width and pitch the same, there won't be wasted bytes and possibly (although I'm not really sure) surface operations will be slightly faster. Maybe not, but who knows, that's why I ask to the people who know. For this to happen, I would need to know beforehand what the pitch of the surface would be, can I assume it will be the same of the screen? I know the pitch depends on the width, but it depends only on the width? I mean, for example, is the pitch always the closest power of two that's greater or equal the width? Is there any other way to know it? it depends on GPU hardware? * PS: You may ask why yet another NES emulator, well I'm planning on doing a different kind and also want to use it as an programming exercise not to let my PHP day job rust my programming skills. But that's way out of the scope of this forum. PS2: I didn't realize this mailing list is reflected as posts on the forum, that's probably why I can't post directly there, because the list does. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Kenneth Bull
Guest
![]() |
![]() |
Since pixels are grouped by rows, not columns, it would probably be
best to have a tile map that is 1 tile across, since then each tile is stored in one block of memory, not scattered around row by row. It'll make it easier to use things like memmove, memcpy, memset, etc. since it will be one call per tile, not one call per row per tile. Other than that, image dimensions should generally be an multiple of 8 or exponent of 2, depending on the hardware. Since you're making an emulator though, I'd suggest keeping it as close to the original hardware as possible. On 22/05/2010, Ernesto Borio wrote:
SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Bob
![]() |
![]() |
On Sat, May 22, 2010 at 1:43 PM, Ernesto Borio
wrote:
Ok, just did a bit of quick research on the NES hardware. Are you talking about the tiles that are used to draw the background of the screen? In that case I would most likely up load them to the video card as individual tiles so that the screen can be drawn by just looking up the "pixel" value in vram and using that as a tile index. So, they would not be in the programs memory at all once they were uploaded. They are small enough to do just that. OTOH, it looks like they can be modified on the fiy by messing with attributes. So, you may have to generate new ones on the fly. Just think of them as being cached values. If you needed on once you most likely will need it again. So, in the code that decides how the tiles look you'll have to check to see it you already have one that looks that way. Of course, I could be completely wrong about how that hardware works. But, the use of a small number of bits to pick a larger tile was very common back then. I would also be wondering about how to scale those tiles so they look good when you scale up for a modern display. NES didn't really have a very good resolution and depended on the effects of an analog, electron gun based display with very slow response time to smooth the graphics. You don't have that luxury.
LIke I said, it doesn't really matter. Ok, that last guy to respond gave you a really big hint. You have a real worry about the real machine works because if there exists a way to abuse that hardware design, that works, some programmer will have found it. I do not know the NES hardware but I do know programmers. If the tiles were stored in a ROM and the ROM is accessed by the NES graphics hardware then there are ways to tweak the hardware to do special effects that the designers of the hardware did not think of. So, you are best off, IMHO, emulating the hardware exactly as possible and only worrying about how you get the images on the screen and the sound to the speakers. Or, to say it another way. I wouldn't be the least bit concerned about that problem. Have you figured out how to tell that the code has gone into a wait for the start of the next vblank so that you can stop running the emulated 6502 machine code and start rendering your emulated screen to the PC display? Bob Pendleton
That is as good an answer as there is for why you would do anything. That is, you want to do it, and you will learn a lot from doing it. I've done jillion projects like that.
-- +----------------------------------------------------------- + Bob Pendleton: writer and programmer + email: + web: www.TheGrumpyProgrammer.com _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Rainer Deyke
Guest
![]() |
![]() |
On 5/22/2010 09:13, Ernesto Borio wrote:
I recently had to rewrite some code that used a narrow, tall texture to store tiles. It turned out that I ran into the maximum texture height for my graphics card when I applied scale4x to the texture. Making the texture more square-ish fixed the problem. This may not apply to you - emulators typically deal with very small data sets - but why risk it? -- Rainer Deyke - _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
Well I thank you all about your NES-related tips, but that's not really relevant here.
I'm of course storing the NES tile data on memory exactly the way the NES did, that's the goal of the emulation, to reproduce the exact system so the system itself can't tell if it's an emulated system or the original physical NES. Besides that, I'm also storing all the tiles in an SDL surface so I can show them on the screen. If I only had the original NES representation, which is 2bpp and the low and high bit of that 2bpp are stored in two separate 8x8 matrix, it would require a transformation every time a tile needs to be stamped into the SDL screen. That's impractical. That's why I keep both the original pixel format of the NES and the SDL 32 bpp tile data that is screen-ready. Right now I'm implementing games that only have tile data in the ROM ( there are games that use tile RAM ) So I know for sure that once the ROM file is read, the tile data is not going to change, so I create the SDL tile sheet once and forget about it. So, keeping a SDL_surface as close as the original hardware (the NES) is not only impractical, but impossible. I like Kenneth's suggestion, that's the kind of tips I was looking for, it may not have a great impact on efficency, but sounds logical. Rainer's remark is also interesting, that may be an issue if I ever try to put this tile sheets in an OpenGL texture or an SDL HWSURFACE, but right now I'm just testing and debugging, so it's not a concern right now. Thanks to all for the answers. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
Is it possible to have a color index that corresponds to a transparent pixel, in a palettized 8bpp Surface?
I see there's SDL_SetColorKey() but it gets a Uint32 as the colorkey, which is a literal RGB value, not a palette index. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Kenneth Bull
Guest
![]() |
![]() |
Yes.
Uint32 is a 32 bit unsigned integer, not necessarily an RGB32 color value. The "key" value is in the same pixel format as the surface, so if the surface is palettized, the key is too. Read this: http://www.libsdl.org/cgi/docwiki.cgi/SDL_SetColorKey _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
So if I set 0 as the colorkey in a palettized surface, every pixel with value 0 will be rendered as transparent?
On 22/05/2010, at 23:00, Kenneth Bull wrote:
_______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Kenneth Bull
Guest
![]() |
![]() |
On 22/05/2010, Ernesto Borio wrote:
Yes. If you're unsure though, test it. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Donny Viszneki
Guest
![]() |
![]() |
On Sat, May 22, 2010 at 2:43 PM, Ernesto Borio
wrote:
Sounds like you should support all those modes and see if they make any difference :)
You typically aren't going to know the pitch beforehand. Making assumptions about the pitch of a surface will certainly make your code a lot less portable to other machines / platforms. I've never seen a platform that caused surface pitch for an arbitrary SDL surface to be a function of the framebuffer width, neither have I seen anything that could be thought of as a "surface" in a way unrelated to SDL behave this way.
It is completely dependent on the SDL back-end video driver, the driver provided to that back-end by your windowing environment, operating system kernel, and yes even your graphics card. In some situations this long chain of considerations may stop at SDL's back-end video driver (take for example the "dummy" video driver -- almost certainly the only need to align pixel data would be to optimize the dummy blitter, but I can't say if it has been done!) -- http://codebad.com/ _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
mattmatteh
Guest
![]() |
![]() |
have you written a working nes emulator yet ?
On Sat, 22 May 2010, Ernesto Borio wrote:
the nes graphics are made up of the tiles, attributes, monochrome, and color emphasis, it would be difficult or wasteful to have all combinations of that within an sdl_surface. and a tile sheet of 256 x 8 pixels is not very useful.
if you have not written an emulator that works yet, i suggest you do. i have written an emulator. the only part of using tiles that maks sense is caching them, that is what i am exploring now. its difficult, you would need to have writting an emulator already that works to understand the complex quirks of the nes rendering. starting with tiles is not a good idea. matt _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
On 25/05/2010, at 12:34, wrote:
I corrected myself in a later mail, the surface is 8 x 4096 px, I.E. 1 x 512 tiles. At first I thought of making this tile sheet 32 bpp, but then realized that applying NES's changing palettes would be a nightmare. So I implemented the tile sheet as a palettized 8 bpp surface with ColorKey = 0. Then when a tile needs to be copied from the tile sheet, the corresponding 3 byte palette is applied to the surface and then it's blitted to the screen. This tile sheet approach is not very suitable for mid-frame and mid-screen scrolling, but I'm implementing this to have a first working version that actually outputs something to the screen, and it should work well with non-scrolling games like Donkey Kong and Balloon Fight, for example.
As I explained before, using a tile sheet is only good for a simple test like the one I mentioned. A better approach would be scanline or pixel based approach. I'm growing my NES technical knowledge while I develop my emulator, it may require a few rewrites along the way, but it's going well so far. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
mattmatteh
Guest
![]() |
![]() |
On Tue, 25 May 2010, Ernesto Borio wrote:
this is what i meant, write one that does all the pixel rendering, then pass the 9 bit pixel array[256][240] to sdl to render. this would also help you debug too. as bob said, you might be wasting time trying to make it efficient the first time. matt _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Bob
![]() |
![]() |
On Sat, May 22, 2010 at 8:52 PM, Ernesto Borio
wrote:
Ok, I'll try one last time. Stop thinking about SDL_Surfaces. Start thinking about OpenGL textures. When you create your images that you want to "stamp" on the screen then you can use alpha blending to set the transparent pixels. Then you can use the hardware in the graphics card to do the painting for you and use the hardware to handle the transparency. Unless you working on some seriously old hardware you do not want to do that yourself. Cells phones do OpenGL (OpenGL ES) now days, with html 5 you are even going to be able to put OpenGL (WebGL) in web pages. Bob Pendleton
-- +----------------------------------------------------------- + Bob Pendleton: writer and programmer + email: + web: www.TheGrumpyProgrammer.com _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Andy Hefner
Guest
![]() |
![]() |
On Thu, May 27, 2010 at 3:31 AM, Bob Pendleton wrote:
Don't bother. The render really is best and most easily done entirely in software, interleaved with the CPU emulation. Generate one line of output for every scanline worth of CPU cycles executed, and copy the whole image to the screen at the end of the frame. As for efficiency, NES emulators were running at full speed on PCs from 15+ years ago. Further, sprite/background priority on the NES is quirky and getting it right isn't just a matter of drawing everything in the right order. A straightforward, unoptimized implementation that does everything correctly can be done in about 300 lines of C. You will never, without unreasonable effort, get it 100% right trying to draw the sprites as images via OpenGL or SDL calls. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
mattmatteh
Guest
![]() |
![]() |
i am experimenting with rendering with tiles now, sure its difficult, but i dont think its that difficult or impossible. there are 2 ways to handle difficult parts, fall back to exact rendering in software when needed, or hack out some complex code to do it all correctly using tiles. matt _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Bob
![]() |
![]() |
On Wed, May 26, 2010 at 4:53 PM, Andy Hefner wrote:
Hey, I do not mean to irritate you. Really, I don't. You sound like you've done this and I have not. Also, I am not the least bit worried about the efficiency of the core renderer. I actually did some coding on 6502 and a lot on the original 8080 and z80. I am very much aware of how easy they are to emulate on modern hardware. I'm also aware of the limits of the graphics hardware from those days. Efficiency was not a worry I had. If you look at the beginning of this discussion you'll see me telling the original poster not to be so worried about efficiency. This is the kind of project where getting it right is hard enough without overloading your self worrying about efficiently before you even have it right. Do you mind explaining the hardware problems that force you to do what you describe? This is just for my own curiosity. I've programmed some fairly strange hardware but those old game boxes did some wild things to keep the build price low. I thought that the graphics wound up at a set in indexes into the tile set and the hardware drew the tiles on the screen based on the indexes. And, I thought the sprite pixels were drawn on top of the background pixels at as part of the process of generating the scan lines. And, part of the process included per pixel contact checks. Generating the indexes, and the sprite processing, has to be done in software. But, it seemed to me that once you had done all that you could just walk the vram and use OpenGL to draw the background tiles all nicely scaled and then draw the sprites, also nicely scaled, with positions based on the processing you've just done. That seemed like it would avoid actually generating the final pixels in software and save a bit of pixel hacking. Bob Pendleton
-- +----------------------------------------------------------- + Bob Pendleton: writer and programmer + email: + web: www.TheGrumpyProgrammer.com _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
petruza
![]() |
![]() |
The NES sprites have some attributes, among them is a bit flag that says if the sprite should be drawn over or underneath the background.
You could think of it this way, there are 4 layers of rendering in the NES: 1) the full screen painted with the background color 2) the sprites that go below the background 3) the background (which of course has pixels with index color 0 transparent so you can se what's below it ) 4) sprites that go over the background But I really don't remember any NES game that has sprites below the background. Not sure how many games used this feature. On 28/05/2010, at 14:53, Bob Pendleton wrote:
_______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Andy Hefner
Guest
![]() |
![]() |
On Sat, May 29, 2010 at 12:53 AM, Bob Pendleton wrote:
Sure. Sprites on the NES have a foreground/background priority bit that describes whether they appear in front of or behind the playfield characters. That alone would be trivial to emulate - draw the background sprites, draw the playfield, draw the foreground sprites - but there's a twist to it. Call it a bug, a design flaw, or just the implementation details showing through. Sprite priority doesn't apply between sprites - a "background" sprite can appear in front of a "foreground" sprite at the same location, if it's at a lower index in the sprite table. That is, the sprites are evaluated in order, with no regard to priority, to produce a color value and priority bit, and only then is the result of that tested against the background. This can cause foreground sprites to disappear behind the background. It sounds like an obscure thing, but quite a few games take advantage of it for simulating the ability of the playfield objects (such a pipe, or the ground) to mask a foreground sprite which should appear/disappear behind it, and where you can't set the sprite itself to background priority because that would prevent you from having any other art in the background where this is going it (you don't want mario to disappear behind clouds or a bush as he starts to descend into a pipe). It's quite easy to emulate if you write your code to generate the image in the same way as the hardware, but achieving it with OpenGL requires some thought (I'm imagining rendering the sprites in reverse order to an offscreen buffer, abusing stencil or depth or something as the priority bit, then combining that with the background in a second pass). The following thread describes the issue: http://nesdev.parodius.com/bbs/viewtopic.php?t=4267&sid=c75e720fd7f10d0e8f974b62db98b77d _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
SDL_Surface dimensions and its efficency | ![]() |
Bob
![]() |
![]() |
Thanks guys. I see the problem. My view was way over simplified.
Yeah, real nasty. While trying to write this reply I've run through several techniques that I thought would work, but when I tried to describe it I saw where it would fail. Thinking about the extreme limits on component counts on chips from those days I can see how this behaviour could be the result of using the simplest possible design for the hardware that checks to see if a pixel should come from the default, the background, or a sprite. Doing it "right" could have added a few more gates and blown the component budget. Thanks for the info. A day when I learn something is a good day! Bob Pendleton On Fri, May 28, 2010 at 12:53 AM, Bob Pendleton wrote:
-- +----------------------------------------------------------- + Bob Pendleton: writer and programmer + email: + web: www.TheGrumpyProgrammer.com _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||
|