• Hello MLAers! We've re-enabled auto-approval for accounts. If you are still waiting on account approval, please check this thread for more information.

Programming: PixMap RowBytes (GDHandle/GDevice)

jmacz

68020
I am clearly missing something so thought I'd ask for some help.

First my environment:
  • CodeWarrior 11
  • System 7.1.1
  • Quadra 800 with two video cards
  • First/primary card: SuperMac Thunder II GX 1360 driving a monitor at 1024x768 in 24-bit color
  • Second card: SuperMac Spectrum 24 Series IV driving a monitor at 1024x768 in 24-bit color
What am I trying to do?

I was poking around with GDevice records by calling GetDeviceList() and GetNextDevice() to walk through them. I am correctly seeing only two devices (the two video cards) and I'm poking into the returned GDHandles and specifically looking at the gdPMap (PixMapHandle) for each of them. I don't have a particular goal. This was just exploratory.

My issue?

My expectation was that the rowBytes inside the gdPMap would be 4096 for both cards. Why? Because I was assuming 32bits per pixel and given the horizontal resolution is 1024 pixels, that should give a rowBytes of 4096.

But what I am actually seeing is 8192 for the Thunder II GX 1360 and the expected 4096 for the Spectrum 24 Series IV. Shouldn't they be the same, at 4096? Trying to understand what I'm missing here.

Data Dump for Reference
  • SuperMac Thunder II GX 1360 @ 1024x768 24-bit Color
    • bounds: left=0, top=0, right=1024, bottom=768
    • pixelType: 16 (RGB Direct)
    • pixelSize: 32bits
    • rowBytes:
      • raw: -24576 ..... 0xa000 ..... 1010 0000 0000 0000
      • highest 2 bits masked off: 8192 ..... 0x2000 ..... 0010 0000 0000 0000
  • SuperMac Spectrum 24 Series IV @ 1024x768 24-bit Color
    • bounds: left=1024, top=0, right=2048, bottom=768
    • pixelType: 16 (RGB Direct)
    • pixelSize: 32bits
    • rowBytes:
      • raw: -28672 ..... 0x9000 ..... 1001 0000 0000 0000
      • highest 2 bits masked off: 4096 ..... 0x1000 ..... 0001 0000 0000 0000
Scratching my head here..
 
The cards are not the same. They don't use the same driver. They don't need to use the same value for rowBytes for the same horizontal resolution and pixel depth.

Some graphics controllers or drivers may prefer a space between rows, or they may prefer a multiple of 8K or any power of 2 greater than or equal to the pixel size. They can do whatever they like, as long as the rowBytes is small enough to fit into 14 bits and the rowBytes multiplied by vertical height is less than the VRAM size. A multiple of 4 bytes will ensure 32 bit aligned accesses. This is the minimum for 24 bit color which usually uses 4 bytes per pixel. A multiple of 8 bytes will ensure 64 bit aligned accesses, which is what you might use on a PowerPC with floating point load/store instructions for faster moving of pixels. You might use a higher power of 2 for cache line alignment. Resolutions usually have a horizontal pixel count that is at least a multiple of 16 anyway which can give an integer number of rows for various standard aspect ratios such as 4:3, 16:9, and 16:10.

Some graphics controllers might use the space between rows for something. The built in graphics controller of the Power Mac 8600 uses the space for storing a hardware cursor.
 
I am clearly missing something so thought I'd ask for some help.

First my environment:
  • CodeWarrior 11
  • System 7.1.1
  • Quadra 800 with two video cards
  • First/primary card: SuperMac Thunder II GX 1360 driving a monitor at 1024x768 in 24-bit color
  • Second card: SuperMac Spectrum 24 Series IV driving a monitor at 1024x768 in 24-bit color
What am I trying to do?

I was poking around with GDevice records by calling GetDeviceList() and GetNextDevice() to walk through them. I am correctly seeing only two devices (the two video cards) and I'm poking into the returned GDHandles and specifically looking at the gdPMap (PixMapHandle) for each of them. I don't have a particular goal. This was just exploratory.

My issue?

My expectation was that the rowBytes inside the gdPMap would be 4096 for both cards. Why? Because I was assuming 32bits per pixel and given the horizontal resolution is 1024 pixels, that should give a rowBytes of 4096.

But what I am actually seeing is 8192 for the Thunder II GX 1360 and the expected 4096 for the Spectrum 24 Series IV. Shouldn't they be the same, at 4096? Trying to understand what I'm missing here.

Data Dump for Reference
  • SuperMac Thunder II GX 1360 @ 1024x768 24-bit Color
    • bounds: left=0, top=0, right=1024, bottom=768
    • pixelType: 16 (RGB Direct)
    • pixelSize: 32bits
    • rowBytes:
      • raw: -24576 ..... 0xa000 ..... 1010 0000 0000 0000
      • highest 2 bits masked off: 8192 ..... 0x2000 ..... 0010 0000 0000 0000
  • SuperMac Spectrum 24 Series IV @ 1024x768 24-bit Color
    • bounds: left=1024, top=0, right=2048, bottom=768
    • pixelType: 16 (RGB Direct)
    • pixelSize: 32bits
    • rowBytes:
      • raw: -28672 ..... 0x9000 ..... 1001 0000 0000 0000
      • highest 2 bits masked off: 4096 ..... 0x1000 ..... 0001 0000 0000 0000
Scratching my head here..

This may be a constraint of the hardware architecture where it can only use certain stride widths for columns. For example, Micron Xceed 30 can do either 512 byte or 1024 byte strides, nothing inbetween. Check the card's vidParams sRsrc records to say for certain.
 
Yes - the point of rowBytes is to tell you how the video device is arranging its memory, not to tell you the width of the screen. Video devices have some (though not a huge amount) of flexibility about how their framebuffers work, and this is one of the ways that is done.
 
P.S. here's an example from aux-minivnc, copying from the card's framebuffer into the VNC client's local framebuffer.

Note here that the source pixmap is incremented by vpRowBytes, but the destination, which is just a flat framebuffer which is always 8-bit colour with no padding, is incremented by the screen X width.

 
For 1992 and earlier (up to Thunder), SuperMac boards had no extra row space, as you calculated above. However, after 1992, there were multiple considerations relating to PowerPC (as suggested above - 1994ish?) and also, possibly, the onboard daughtercard accelerators (GX). Either of those issues could have affected row spacing.

You will also note offsets in the baseAddress on later SuperMac cards -- maybe anything Spectrum/24 PDQ (original) or later. The reason for the offset is because of bug/"feature" in QuickDraw that could potentially bus error the machine by performing bit-field extract (bfextu) during copybits operations at the origin in certain circumstances (screen with menubar). For visible areas/screens aligned to the exact start of physical memory, QuickDraw would bus error the Mac by trying to access memory that didn't exist. So, by moving the base address forward (adding a small memory buffer), there was protection in the event that QuickDraw attempted an access memory beyond the screen origin. And, because the older boards used 100% of RAM, it wasn't possible to fix this kind of issue in 24-bit mode. I think I mentioned this problem elsewhere and that Apple eventually fixed this problem in later OS releases.
 
Back
Top