Sign in to follow this  
Madolite

Drawing graphics in C++ w/out APIs?

Recommended Posts

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.

Edited by Madolite

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites


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).

Share this post


Link to post
Share on other sites


Can you communicate directly with drivers and graphics card using C++?

Absolutely.

 

There's two layers:  the OS layer and the userland layer.

 

You can examine the source code for both of these layers if you look at the open drivers for the Linux operating system.  No magic.  It's all just C code (likely compilable wit ha C++ compiler, because that's what C++ is all about).

 

At the lower (kernel) level, the GPU has a bunch of memory-mapped registers (ie. you read or write data at a specified memory location and it sets or gets values from hardware registers).  A lot of GPUs have dual-ported memory (ie. they can read and write data from the CPU's main memory).  There's often interrups as well:  these are events triggerd by the hardware the need to be handled by the CPU, but are really just subroutines in the kernel driver.  All drivers these days at least for the Linux kernel tend to be written in C and C only, for portability.

 

If you choose to write your own driver using C code, it's not going to be portable.  That's the whole raison d'etre of an API like OpenGL:  it hides all the ugly hairy and warty bits behind a thin layer of stretchy fabric so you can sleep at night.

Share this post


Link to post
Share on other sites

In the interest of fairness I would like to point out that devices that use port-mapped i/o can't be accessed from pure C/C++ - that requires platform- and compiler-specific extensions.

 

Fair point. The first by definition, and the second as a matter of C and C++ not defining port-mapped i/o in its abstract machine -- but still, I took OP's intent as "without intervening APIs or drivers; possibly bare-metal", not "100% standard C++: portable and cross-platform." 

Share this post


Link to post
Share on other sites

 

In the interest of fairness I would like to point out that devices that use port-mapped i/o can't be accessed from pure C/C++ - that requires platform- and compiler-specific extensions.

 

Fair point. The first by definition, and the second as a matter of C and C++ not defining port-mapped i/o in its abstract machine -- but still, I took OP's intent as "without intervening APIs or drivers; possibly bare-metal", not "100% standard C++: portable and cross-platform." 

 

 

I only brought it up for the sake of completeness anyway since port-based i/o is so rarely used nowadays.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this