# Aros/Developer/Docs/Libraries/CGFX

* Navbar for the Aros wikibook
* Aros User
* Aros User Docs
* Aros User FAQs
* Aros User Applications
* Aros User DOS Shell
* Aros/User/AmigaLegacy
* Aros Dev Docs
* Aros Developer Docs
* Porting Software from AmigaOS/SDL
* For Zune Beginners
* Zune .MUI Classes
* For SDL Beginners
* Aros Developer BuildSystem
* Specific platforms
* Aros x86 Complete System HCL
* Aros x86 Audio/Video Support
* Aros x86 Network Support
* Aros Intel AMD x86 Installing
* Aros Storage Support IDE SATA etc
* Aros Poseidon USB Support
* x86-64 Support
* Motorola 68k Amiga Support
* Linux and FreeBSD Support
* Windows Mingw and MacOSX Support
* Android Support
* Arm Raspberry Pi Support
* PPC Power Architecture
* misc
* Aros Public License

## Introduction

cybergraphics.library is a 15, 16, 24 or 32 bit graphics board extension for the native graphics.library. Up to OS3.1 there are no possibilities to add custom boards into the display database in a system friendly fashion and so it instead patched some of the original graphics functions in order to integrate custom graphics boards into the system.
Nearly every standard 8bit application will work on this 15/16/24 bit screen. But it only can use the additional features, if it knows of CyberGraphics, of course.

## Writing Pixels

For writing pixels, reading Pixels and blitting, there are the functions FillPixelArray, MovePixelArray, ReadPixelArray, ScalePixelArray, SwapPixelArray, WritePixelArray and WriteRGBPixel.

## Bitmaps

Starting with OS 3.x two new graphics calls were added to support bitmap creation and removal: AllocBitmap (graphics library) and FreeBitmap (graphics library). With these calls the first step was made to allow custom bitmap formats. Before it was no problem at all to directly render into the planes or to make assumptions about the structure of the bitmap data. To get more information about the bitmap data use GetBitmapAttr (from graphics library). With this one you could get information on the width, height, depth and certain flags of the bitmap.
This was the first step into the RTG direction, ie like adding a depth attribute to AllocBitMap etc
As soon as GetBitmapAttr(bm,BMA_FLAGS) didn't return BMF_STANDARD, the bitmap was not direct accessible anymore and could only be accessed by attachment to a rastport and subsequent rendering calls or by using blit calls with a standard bitmap as destination.
Unfortunately many programs didn't follow these guide lines and didn't check for the BMF_STANDARD flag with OS3.0 and above. Cybergrphx version of GetBitMapAttr (bitmap, P96BMA_MEMORY) has to use LockBitMapAddress with LBMI_BASEADDRESS and don't forget use LBMI_BYTESPERROW either.
With CyberGraphX you also have to add BMF_MINPLANES in the flags field of AllocBitmap/gfx. It is also possible now to allocate device dependent pixel format bitmaps and standard 15/16/24/32 bit depth image maps. Therefore new bits in the 32bit flags field parameter of AllocBitmap have been added. If you specify the BMB_SPECIALFMT bit (see includes), the upper 8 bits of the flags longword contain information on the pixel format of the requested bitmap.

### Lock BitMaps

Once allocated, you can attach the returned bitmap to a rastport and do rendering calls. It is NOT possible to attach this bitmap to a screen by supplying it as custom bitmap with OpenScreenTagList !!
You are not allowed to directly poke into the bitmap image data as long as the bitmap isn't locked. The location and contents of the image data is subject to change and is only valid when it's locked by using the available locking calls. LockBitmapTags/UnLockBitmap has been added for this purpose. You HAVE TO supply a taglist with LockBitmapTags which contains pointers to longwords which are filled with valid data if the call returns with a non-zero value. Only if a non-zero value is returned you are able to access the bitmap directly! Check the address you get back with the LBMI_BASEADDRESS tag. This is the base address you can do your rendering to.
which flags needed for AllocBitMap to create a lockable bitmap? anything else resulted in a "no lock" message
Is there some function that returns whether a locking of the bitmap works ? No. The cgx autodocs say that LockbitMap will return 0 if the bitmap could not be locked. It does not say that a bitmap which was successfully locked once, can be successfully locked every time. So a function telling whether bitmaps are lockable or not would not really help.
I would make the code check return value of LockBitMap. if it is 0 (failure) do the workaround (WritePixelArray, otherwise do direct bitmap access. Or if this for some reason is not optimal/working, make it configurable whether program shall (try to) use LockBitMap or not.
Otherwise for vice this means that will have to do a 'test' lock and see if it works, if it works the code can use the lock code and otherwise it needs to use the WritePixelArray code.
Even though that may work with current drivers, think it would be better to check the retval each time at every LockBitMap call.
It would be so much easier if aros had some backup code for this. For example if a bitmap lock is not supported but it is called anyway, aros allocates a buffer, copies the bitmap into it, gives the caller the address of the buffer, caller does whatever, when the lock gets released aros copies back the bitmap (or if it's faster, only the changes), and releases the buffer.
As said, this would be slow. But if you want you can try that out yourself by writing your own MyLockBitMap functions which works like you described.
It's possible, but it would be very slow as it is unknown what the LockBitMap caller will do. What parts of the bitmap he will access. Whether he will read pixels, write pixels or do both. So the fallback code would need to alloc a pixel buffer and read the whole bitmap into it.

### OffScreen BitMap

All drawing functions work on a bitmap. A rastport is basically just some structure which contains the graphics context (foreground color, line pattern, drawmode). Most drawing functions require a rastport. (a rastport does not automatically come with it's own bitmap!).
You create some rastport. You create some bitmap. You connect the two (put a pointer to the bitmap into the rastport). Then you render into rastport and it will go into your bitmap:
If using a windowed application running on a 15-bit (or higher) Workbench. The application uses an offscreen BitMap for rendering, the contents are then copied to the window with a ClipBlit. Assuming my offscreen BitMap is a friend of the Workbench screen Bitmap and is at least 15 bits deep, how do we arbitrarily set the colour we want to draw with? Basically you will need to GetColorMap, followed by a number of SetRGB32CM.
So how can we take a pointer to that and feed it to ObtainPen to get my custom drawing colour, right? Better use ObtainBestPen.
allocating bitmap in same format as screen (wb) bitmap for best performance:
bm = AllocBitMap(width, height, depth, BMF_MINPLANES, screen->RastPort.BitMap);
Connecting rastport with bitmap:
Note though that this way you don't get any clipping at all, so do not render outside of the bitmap dimensions or it will crash (not necessarily happens under AROS/hosted/x11 as x11 clips everything).
If you really need clipping as well then you would have to install a layerinfo plus some layer connected with your bitmap and then use layer->rp as rastport.
You need to differentiate between indexed and truecolor by force. To draw single pixel in indexed mode there is graphics.library/WritePixel. To draw single pixel in truecolor mode using an RGB value there's cybergraphics.library/WriteRGBPixel.
To draw multiple indexed pixels there's graphics.library/WritePixelLine8 or WritePixelArray8 or WriteChunkyPixels. On truecolor screens drawing multiple *still indexed* pixels there's cybergraphics.library/WriteLUTPixelArray.
To draw RGB pixels on truecolors screens you can use cybergraphics.library/WritePixelArray(rectfmt = RECTFMT_RGB or RECTFMT_ARGB or RECTFMT_RGBA).
RGB = R8 G8 B8 R8 G8 B8... ARGB = A8 R8 G8 B8 A8 R8 G8 B8... ...
in memory, independent of endianess of computer.
The pixel buffer will be converted to the destination bitmap pixel format automatically but this conversion may be slow as we have only one general slow conversion routine.
Better would be to use RECTFMT_RAW which means same pixel format as destination bitmap. Then you would have to do the conversion yourself before calling WritePixelArray(RECTFMT_RAW).
Unfortunately there's no special function to do something WritePixelArray-like-but-with-mask.
line drawing: well, that's done through Move(rp, x1, y1) and Draw(rp, x2, y2). At the moment this is tough only with tricks usable using a specific RGB color of your choice on a truecolor screen. By default color is pen/indexed based, both on indexed screens and truecolor screens where color is set with SetAPen.
There's no such thing for polygon functions, unfortunately. At the moment those are rendered old-style in software by graphics.library into a 1-plane bitmap and then put into destination rp/bitmap using BltPattern.
By the way, the BitMap you get with the AllocScreenBuffer command is the same as the screen's, so it's suitable for accelerated operations. You would just link the bitmap in the screenbuffer to a RastPort to use with the graphics library commands that need one. Again, that's on the Amiga. It would be nice to get this working in AROS as well.

### Buffering (Double or Multi)

Start up code

#### DBufInfo dbi

Only these are to be used dbi_SafeMessage, dbi_DispMessage, dbi_UserData1 and dbi_UserData2

#### ScrollVPort

here's my double buffer algorithm for cybergraphics screens: I allocate a screen twice the height (non draggable), do all my off-screen rendering in the non-viewable section (the bottom half usually) and when I'm done I do one huge blit (ClipBlit) to copy everything in the bottom half up to the top, viewable area of the screen. This works pretty quickly even on big screens with high depth.

#### ChangeScreenBuffer (Aros Broken?)

Sources here
The idea being that ChangeScreenBuffer returns zero if it can't do the flip and probably does the signal checking stuff internally. For double buffering you use standard Double Buffering functions like the functions around AllocScreenBuffer.
There is also a Commodore example doublebuffer.c to look at as well as CyberAnim13.lha.
Instead you should use WritePixelArray or WriteLUTPixelArray from CGX API or WriteChunkyPixels from graphisc.library. Please note WriteChunkyPixels is available only in Kickstart 3.1 so you have to add fallback routine for 3.0 users.
Please note you can not write directly to bitmap which dont have BMF_STANDARD flag set!
Take a look at CGX devkit. It explains what restrictions you have with RTG systems, and what you should take into account (especially that BMF_STANDARD flag in bitmaps).
Is there any way to avoid the excessive blinking and have the display behave more like normal ?
AROS at the moment has only one general non optimized RGB format conversion routine which is of course slow. There are no special one for common cases like ARGB32 to RGB15. You could do the conversion yourself and then use RECTFMT_RAW.
gray bars/blinking. Do you WritePixelArray directly into window RastPort? It's unlikely original code (if using LockBitMap) did that, so you shouldn't either, if that's not a whole "frame" which is written at once. Either collect pixels in a whole frame pixel buffer and do WritePixelArray to window, once a whole frame is "ready". Or WritePixelArray into a offscreen bitmap and BltBitMapRastPort that to the window, once a whole frame is "ready".
Or it could be the double buffering functions (AllocScreenBuffer, ChangeScreenBuffer,...) which are not yet working in AROS.
Could AROS's CGFX implementation not just use an internal lookup for RECTFMTS that is "correct" for whatever arch?
Programmer writes RACTFMT_BGR32 -> CGFX interprets it before performing the normal action? or would it be too much of a slow down? There's no need to change anything in the CGFX implementation. Only some optional redefining of the pixfmt/rectfmt ids in libraries/cybergraphics.h
What exactly does WritePixelArrayAlpha do on AROS? From BM__Hidd_BitMap__PutAlphaImage in workbench/hidds/graphics BM_Class.c. That's the fallback code when the gfx drivers do not override reeimplement it.

## ScreenMode

Cybergrafix supports some very fine functions to select a screenmode, for example BestCModeIDTagList, which gets the best screenmode for a specified tag list of screen attributes.

## Pixel Formats

The following pixel formats are available:
Many of this pixel formats are device specific and should not be used, recommended formats are PIXFMT_LUT8, PIXFMT_RGB16, PIXFMT_RGB24 and PIXFMT_ARGB32.
Get the value of the LBMI_PIXFMT ULONG field to get information on the colormodel you have to use for image rendering. ALL models have to be supported! The other fields give you information on the layout of the bitmap data. It should be no problem, to directly render into the bitmap anymore. Keep in mind that all this values are only valid until a subsequent call to UnLockBitmap. Afterwards you have to lock the bitmap again. Don't hold this lock for longer than one frame! You may use the standard graphics.library bitmap blitting calls to copy the bitmap contents to another bitmap. Copying truecolour bitmaps into indexed colour chunky bitmaps is not supported by now.
locking the bitmap to write directly into gfx card memory will require that you use cgx functions. Otherwise you'll have to use WritePixelArray like functions. Opening cgx library is good since it works with classic miggies with rtg (both cgx & p96 will work)
how to fix direct bitmap access. First I want to remove extended pixelformat definitions:
They can confuse programs because they don't know about them. Additionally, 0RGB32 (for example) is effectively the same as ARGB32, which is the standard definition. The only question is ABGR32 format. It is expected to be other-endian version of RGBA32. And I'd like to check if some GFX cards are actually using ABGR32.
On such cards monitorclass test will report that none of known pixelformats are supported. Monitorclass does not work with extended pixelformats, as a test. If not, I'll leave ABGR32 format in the specification but give it number 14, next to RGBA32. This will be much more comfortable for monitorclass (it uses a pixelformat-indexed array in one place).
Currently only one driver that uses RGBA32 format. It's Windows-hosted driver. Windows GDI uses this pixelformat internally. If we imagine Windows on bigendian CPU, it will become ABGR32. On the other hand, there will never be any more bigendian CPUs in the world. Additionally, this is fixable by the software.
Getting rid of bad pixelformat codes in CGX will almost do the job. The other thing will be endianess conversion removal in some software. Pixelformat describes how pixels are laid out in RAM, so there's no need to swap bytes.
* Rendering directly to bitmap works, but only if gfx driver supports it. Nvidia driver does, most others don't.
* Pixel and rectformats in AROS cybergraphics always refer to the layout in memory. So RECTFMT_ARGB means 0xAA 0xRR 0xGG 0xBB. And this is so no matter if running on big endian or little endian machine. This is important to know for when running on little endian (x86) machine, because then if you have an ULONG pixel array/buffer where you write ARGB pixels into it using pixel (ULONG) accesses then in memory it will look like 0xBB 0xGG 0xRR 0xAA and you would need to use RECTFMT_BGRA.
If you have a screen using PIXFMT_RGB16PC, but WORD pixelbuffers then on AROS little endian you would need to use RECTFMT_RGB16 and only on AROS big endinan RECTFMT_RGB16PC.
Since this actual meaning of rectfmts/pixfmts is sometimes not very nice intuitive (#if AROS_BIG_ENDIAN do_this #else do_that) there are plans to modify libraries/cybergraphics.h so that it switches meaning of rectfmts pixelformats from being "based" on memory layout to being based on pixel access.
Btw, there's also RECTFMT_RAW which means same format as bitmap format.
Could AROS's CGFX implementation not just use an internal lookup for RECTFMTS that is "correct" for whatever arch?
Programmer writes RACTFMT_BGR32 -> CGFX interprets it before performing the normal action? or would it be too much of a slow down?
Is using WritePixelArray any faster to an offscreen bitmap (one not allocated to be visible) ?
hardware accel: gfx drivers could override/reimplement PutAlphaImage method if they want. But I do not know how much sense that makes or if it's possible at all as with WritePixelArrayAlpha you have an ARGB pixel buffer which will likely be in RAM. Gfx cards if they can accelerate this might need the pixels to be in VRAM. I don't know.

## Endian

This is an endianess thing. On AROS big endian it's exactly the same as in AOS/MOS. Because pixel access/component access/memory layout on big endian machine does not make a difference. If you write a 0xAARRGGBB ULONG to memory it will be 0xAA 0xRR 0xGG 0xBB in memory, too. Same thing. No problem.
On little endian machine it was something of a design decision whether the RECTFMTs/PIXFMTs should reflect pixel access based meaning (unit == pixel) or memory layout based meaning (unit == byte or component). Because RECTFMT_ARGB does not mean that one by force always uses ULONG pixel buffers and only ULONG pixel accesses. One may also use byte/component access. Or read/write such pixel buffers to/from disk.
But if you do not like that it can easily be fixed by adding something like this to your code:
At least for the moment. As said it's anyway planned to add such an option to libraries/cybergraphics.h. Then you would do a #define CGX_PIXEL_BASED_FMT_IDS (or some better name) before including libraries cybergraphics.h and be done.
Apps using the original cgfx functions (and attributes for functions like GetCyberMapAttr) should never see this values.
Yes, however only GetCyberMapAttr processes this. Other places pass them on to applications.
a CYBRMATTR_PIXFMT_ALPHA was introduced, too, which means "do not map, I know about the 0RGB32, etc. pixfmts". In case you want to keep that.
While driver_GetCyberMapAttr for example seems to map the 0RGB32, BGR032,... correctly to ARGB32, BGRA32,... so that (legacy) apps get only values they expect. In other places (which callc hidd2cyber_pixfmt) this is missing/was forgotten to be fixed.
You could (*) add a BOOL param to hidd2cyber_pixfmt function which indicates whether or not to map the 0RGB32, etc. to ARGB32, etc. And then pass FALSE in most functions which call hidd2cyber_pixfmt.

## CGFX Fix For Cairo

Cybergrafix supports a function to get some information about the (modified) Bitmap structure, but (sadly) you do not get the address of the video memory. So you can't write directly to the video memory.
For historical reasons related to the Cybergraphics API, graphics.hidd will set the alpha value to 0 when reading 24->32 bits or writing 32->24 bits. pixman will (correctly) interpret the pixels as being transparent. SO before we feed the pixel data in to cairo, we have to fix it by forcing the alpha value to 0xff.
Its complicated further by the fact that we have to handle the non-native endian RGB format as well. The two available formats are (effectively) xRGB and xBGR. For xBGR, we do an endianness swap then shift down before adding the alpha; that is xBGR->RBGx->0RGB->ARGB.
One day graphics.library will give us a way to request this from the graphics.hidd format conversion routines, and this won't be necessary.
Our CyberGraphX API has BltTemplateAlpha and WritePixelArrayAlpha, and they work. Other functions do not process alpha channel, because they are not intended to do it. For CGX ARGB pixelformat actually means 0RGB.
I think this is specifically about hardware alpha handling:
Fix up Hardware & Software Alpha channel support in graphics.library and gfx.hidd
* Must enable at least one hardware alpha capable driver to demonstrate functionality.
* Must also provide a test application demonstrating it in use.
I think currently all drivers implement PutAlphaImage via a software method. I borrowed the implementation in nouveau from nvidia if I remember correctly and the implementation is:
For each pixel of alpha enabled image, check if alpha is different than 0 or 0xff, if yes read the pixel from VRAM, apply new color with alpha and write it back. Reading from VRAM is terribly slow, thus our Decoration, which uses alpha images, seems very slow when you had several windows open and moving them around.

## Examples

On the other hand to draw in the screen you could also use a generic function like: WritePixelArray8(rastportptr, 0, (bufferactual-1)*(pantalla->Height/numerodebuffers ),319,199,(UBYTE *)chunkybuffer, NULL);
WritePixelArray ( ) ? Look up on the cybergfx functions, they are very easy and do a lot of pixel conversions for you.
http://thomas-rapp.homepage.t-online.de/examples/dtwin.c
The tags... PDTA_Remap,TRUE,PDTA_Screen,scr,PDTA_DestMode,PMODE_V43... should enable palette remapping.

## References
### ImageClass

You create a new boopsi class which is subclass of Intuition's IMAGECLASS (like this bitmap class) and in the IM_DRAW method you do the painting in whatever way you want. If you have some Bitmap from the datatype object use that with BltBitMapRastPort, if you have some chunky pixel array, use WritePixelArray.
See compiler/coolimages/imageclass.c
Objects created from classes derived from IMAGECLASS can be passed to DrawImage. from Converting struct BitMap into struct Image
If using native format bitmaps for the gfx hardware but how can it ensure they have Alpha? And since its impossible to lock access to the bitmap in most drivers how can it get access to the raw array of pixel data to pass into the Alpha functions in AROS? the pixfmt to use with the function can easily be obtained from the bitmap but until it is possible to get the data to use, it's pointless.
All the normal blit operations should respect alpha anyhow - and apps should determine if they will use it by allocating bitmaps without alpha etc. (since they should know if they support/need it or not).
All gadgets will be drawn using PutImageAlpha (slow) while if using BltNewImageSubImageRastPort as previous, an attempt is made to check if the subimage of bitmap has no alpha channel pixels and if yes, a regular bitmap copy (CopyBox) is being done (faster). The image conversion method it is checked whether a subimage has not alpha pixels and if yes this subimage is marked as "able to copy from bitmap" instead of using WritePixelArrayAlpha. As a solution is the following:
* in the CreateNewImageContainerMatchingScreen function move the "transparency per subimage" test to main code path out of truecolor only
* don't assume that in LUT case all subimages can be read from bitmap, but re-use results of "transparency per subimage" check
This way you will cover all cases with BltNewImageSubImageRastPort, because it will detect (->subimageinbm[i]) that some images can't be copied from *bitmap and have to be drawn using WritePixelArrayAlpha regardless if the screen is LUT or truecolor. This also means BltNewImageSubImageRastPortSimple can again be based on BltNewImageSubImageRastPort.
If you want to keep the background pattern, you should move the WritePixelArrayAlpha in place of the ClearScreen.
Also, note that ClearScreen doesn't do what you seem to think it does - it does *not* clear the entire window, it clears from the current position, which since you haven't done a Move after writing the text will be *after* where the text is located. ClearScreen only clears from the current cursor position to the lower right end. In order to clear the entire drawing area, do Move(0,0) first.