Drawing graphics in C++ w/out APIs?

Started by
12 comments, last by Anthony Serrano 8 years, 6 months ago

What is the lowest possible level of C++ (bottom up) I can use to draw graphics on a custom, non-console screen window? Is OpenGL the minimum requirement for drawing graphics, or was openGL itself written in C++ (and therefore, you could essentially write your own openGL-like API)? Can you communicate directly with drivers and graphics card using C++?

I guess my question's bottom line is this: How does C++ communicate with the graphics drivers and hardware?

I know I'm probably never gonna need to do this (I can just use SFML or whatnot), but I just like to know out of curiosity. Thanks in advance.

Advertisement

Basically you would still need some API to put your frame buffer on the screen on any modern OS. Then the framebuffer could be how it used to be in the old days (look up mode 13h or mode x -vga programming) a linear array of memory. The first element of the array corresponds to the top left corner of the screen and increasing addresses follows the pattern of the raster of CRT displays (scanning left to right - top going down). Then you could plot points by calculating the address of the pixel you wanted to draw. There were also line drawing, polygon filling, sprite drawing... The only book I can think of is Abrash's Zen of ...graphics? Have to check for the exact title. What exactly do you want to do?

-potential energy is easily made kinetic-

You can write a software rasterizer -- basically you create a region in memory that's an array of pixels, and then you write your own individual pixels into it. When you're finished, you can use you host's windowing system to display it, or you can shuffle it off to OpenGL/Direct3D through the usual layers, but not using any of their drawing routines. In the old days of DOS that's how graphics were done, except DOS was single user so you could take direct ownership of the graphics adapter's memory and write straight into it.

Drawing pixels, lines, circles, elipses, and bitmaps this way is pretty typical of a 100-level course in computer graphics. A 150 or 200-level course often extends this to 3D, where you first transform the 3D geometry in a software rendering pipeline, and then you rasterize shaded and texture-mapped triangles to the bitmap.

On most platforms you can't easily talk directly to the GPU, and GPU vendors aren't terribly open about their drivers' API surfaces or hardware command registers (Though, they've started being more open lately with the call for open-source drivers) and even if they were you're talking about 2000 pages or more of datasheet to get your head around.

If you want to talk directly to a GPU, your best bet would be something like the DreamCast or Raspberry Pi, but understand that even those "simpler" systems are vastly complicated, and the act of talking to them at a low level doesn't look much like graphics programming, if that's the part that interests you.

throw table_exception("(? ???)? ? ???");

You definitely can communicate directly with the graphics card in the same way that OpenGL does. If you're interested check out the source code for some of the open source graphics drivers developed for linux. The issue is that these drivers are very much hardware specific and will not work for chipsets from other manufacturers, and only for certain models of that chipset.

If you aren't concerned about OpenGL you can access the hardware with VESA or even VGA. VGA 320x200 was pretty easy to work with. I haven't done it personally since I was working with Turbo C on my 286...

I guess my question's bottom line is this: How does C++ communicate with the graphics drivers and hardware?


The communication must be done in a platform-specific way. You cannot use "just" C++ to interface with graphics drivers or with hardware. Modern OSes outright forbid you from doing so without going through their driver interfaces, which will require coding to OS-specific APIs and such that are far more complicated and onerous than OpenGL is. Without an OS getting in the way, talking to hardware still requires poking interrupt handlers and hardware registers and DMA transfers and so on, none of which can be done with pure C++.

Even OpenGL suffers from these problems, though people often forget it. You can't, for instance, just create an OpenGL window and use it form C++. The actual creation of a window, loading of a driver, and most importantly the creation of GL context are platform-specific extensions (WGL for Windows, GLX for Linux/X11, AGL for OSX, EGL for mobile+, etc.).

The OpenGL driver on your platform has a bunch of platform-specific code to allow your simple OpenGL C function calls to be transformed into the appropriate OS driver calls, which then (probably) interface with the OS's driver framework to talk to the hardware.

Even if you render images in software, you eventually have to interact with that stack to get your image on the user's screen. C++ has no ability to do that itself.

Sean Middleditch – Game Systems Engineer – Join my team!

Back in DOS days with VESA LFB you'd just go...


unsigned char *buffer = (unsigned char*)0xA0000;

buffer[0] = 255;
...and BAM! Blue pixel. (Not QUITE that simple, but close enough).



http://www.drdobbs.com/parallel/using-the-vesa-bios-20-linear-frame-buff/184409699
To answer OP's question directly: It is simply impossible.

The C language itself has no ability to communicate with anything other than memory. The C standard library, among other things, provides basic I/O to file descriptors: stdin, stdout, stderr, and files. However, before you can even read or write to descriptors as described by the C standard library, there must already exist an API exposed by the operating itself to facilitate such means, and there must be a platform specific library which links platform-independent code to platform-specific code (the C runtime library). In a sense, Nypyren's example relies on a API. The BIOS itself (and/or DOS) exposes services to allow interaction between the software and the hardware. Why doesn't the C standard library "just provide" all these fancy things? Because it cannot guarantee that all platforms can support it. What good is platform-independent code, if platforms cannot support it? To put it bluntly, "(C and C++) doesn't even require your system to have a screen or keyboard"!

This isn't to say that APIs are bad. These days, there are so many layers of abstraction, it's unavoidable. APIs are absolutely necessary, and you must take the time to understand the libraries you use in order to write a well behaved program. If you're looking to get down to the wire with real-time software rendering, then you can use either your platform's API to create and window and blast pixels, or use a cross platform library to do it for you. Either way, there will be some cost in learning a new API.

But it's worth it.

Your opengl implementation will probably be written in C. It'll communicate with the GL hardware by loading blocks of instructions and data into shared memory. Exactly how to achieve this is often commercially sensitive information -- the various device manufacturers are in competition with each other for speed... and consider the actual hardware APIs to be part of what constitutes their commercial advantage. This is why even the Linux drivers are often opaque code blobs (upsetting purists) instead of readable source.

Why do you want to do this?

Quite apart from anything, getting it working on one card with one kind of GPU won't give you much portability...

Allright guys, thanks for the answers. Just a question out of curiousity anyways. Cheers. :)


Without an OS getting in the way, talking to hardware still requires poking interrupt handlers and hardware registers and DMA transfers and so on, none of which can be done with pure C++.

Well, that's not quite true. You certainly *could* do those things if you had access to (and understood) the bare-metal. Its true of course that going through at least a BIOS is common and more than enough "to the metal" for most everyone's tastes, but there's nothing inherently special about a BIOS; its just machine code implementing an abstraction layer over the barest of hardware. All those interrupt handlers and hardware registers, including those that control DMA, can be reached from the CPU, so I don't understand how that would prohibit C++.

Agreed, though, that its entirely impractical to attempt talking to modern hardware and getting modern features out of it. If that's your hobby, take up driver development, but even that's done at a substantially higher level of abstraction (with the OS providing IOCTL interfaces and other necessary or useful primitives).

throw table_exception("(? ???)? ? ???");

This topic is closed to new replies.

Advertisement