Thread: Creating graphics from scratch

  1. #1
    Registered User
    Join Date
    Nov 2013
    Posts
    107

    Creating graphics from scratch

    I am trying to work out how you do this from first programming principles. I know you have DX and GL and API's like the WIN32 API.

    However what is going on behind the scenes with these API's. For example in the WIN32 API you have,

    Code:
    HANDLE WINAPI LoadImage{..}
    So I am assuming that this load image function is(and only can be) written in Assembly language?

    Where is the fundamental point where you are telling the graphics card that this data I am sending is an image and it's to be displayed with xyz attributes, such as RGB values, position, and lighting effects?

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    LoadImage is probably written in C or C++. In the Win32 API, you can allocate a device context, or get a handle to an existing one, and use drawing functions to draw on that context. The context could be an off-screen buffer, the physical screen, or a window.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User
    Join Date
    Nov 2013
    Posts
    107
    Quote Originally Posted by Elkvis View Post
    LoadImage is probably written in C or C++. In the Win32 API, you can allocate a device context, or get a handle to an existing one, and use drawing functions to draw on that context. The context could be an off-screen buffer, the physical screen, or a window.
    But that's the point, what is a device context, what language was it written in, also drawing functions. There are no drawing function in C/C++, yes there are in the WIN32 API however how can API drawing functions be written in C/C++ if it doesn't have any, you would be using some external library/API somewhere down the line that couldn't be written in C/C++? The same applies to DX/GL these can't be written in C/C++ as stated before, do Nvidia and AMD have there own hardware specific language that can directly control the graphics cards?

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Just about the only operating system code that is typically written by hand in assembly these days is the boot sector code. It's a 512-byte stub that initiates the loading of the OS kernel. Nearly everything after that, with the exception of some very special-purpose code (paging, protected mode, hardware interrupt handling), is written in C and C++, at least in Windows.

    As for drawing functions, I'll give you a C example, based on the old 320x200 graphics mode of a standard VGA card. I recommend that you not try this on a modern OS. This only works if your code has direct access to the hardware memory buffer, such as DOS with a DOS extender or other DPMI interface:

    Code:
    typedef unsigned char byte;
    static byte* vgaScreenBuffer = (byte*)0xa0000;
    
    void putPixel(int x, int y, byte color)
    {
        if (x >= 320 || y >= 200 || x < 0 || y < 0) return;
    
        vgaScreenBuffer[(y * 320) + x] = color;
    }
    As you can see, there's no need for language or standard library drawing functions. We create our own, that directly access memory. All other graphics functionality is built on top of basic functions like this. Different graphics modes will call for different implementation details, but this should give you a general idea of how things work.

    Quote Originally Posted by jim_0 View Post
    do Nvidia and AMD have there own hardware specific language that can directly control the graphics cards?
    Sort of. There are compilers that generate native GPU code, but the high-level code is still often written in C, and then compiled to produce native GPU machine code.

    If you're seriously interested in the low-level implementation details, I suggest you have a look at ReactOS. It's an effort to produce an open-source windows-compatible operating system. You can check out the source code, and learn all you want about how those things are implemented.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  5. #5
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Sounds like you are talking about the renderer. The renderer is the last phase of the graphics pipeline that takes as input a set of points (triangles), colors, texture coordinates, etc. and is responsible for drawing the output. These days most renderers are encoded in hardware on the graphics card, but there are software based APIs like MESA 3D that don't require a OpenGL card. Understanding a renderer is mostly about understanding the mathematics behind 3D graphics; I doubt looking at the code would be very interesting or revealing. Basically all it does is output pixel values based on some complex algorithms.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    I don't think jim_0 is even talking about 3D graphics. Just drawing basic graphics to the screen like pixels, lines, shapes, and images. No complicated formulas are necessary. I'd recommend a google search on computer graphics primitives, along with looking at the source for ReactOS, which I linked above.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  7. #7
    Registered User
    Join Date
    Nov 2013
    Posts
    107
    So your saying there are certain memory mapped locations and when you write to them they triigger some hardware event, in other words, they send data to the GPU. These seems to be 0xB8000 and 0xA0000?

    If correct, are there more memory mapped addresses or just these two?

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    So your saying there are certain memory mapped locations and when you write to them they triigger some hardware event, in other words, they send data to the GPU.
    O_o

    You are near the mark.

    The VGA information referenced is part of "Real Mode". You, basically, call a couple of functions which tells the BIOS to load a simple video driver for you. The BIOS then communicates with the video card through the driver using a shared protocol which then, assuming the card supports the standard, copies the data from the relevant address before doing whatever magic is necessary to push pixels onto the display.

    o_O

    I can write code to push pixels onto my display using the BIOS VGA modes over HDMI even though the code does not speak the HDMI protocol. I can write such code only because the video card talks to the display on my behalf. (You'd find, if you looked, that not all video cards would support the combination.) I am still not actually "creating graphics from scratch" because multiple layers have insulated my code from the hardware.

    I've made an 8 by 8 pixel LED display for fun. I wrote the code to drive each LED which hangs off some controller.

    I've also written a few simple games and things for the Gameboy Advance console which gives you something not unlike the BIOS VGA modes.

    I've used C++ for all of such things. I have a tiny, four of five lines, of assembly that talks to the BIOS for me just long enough to setup VGA mode. The manufacturer for the controller I used ships a C library which is nothing but a thin wrapper over the assembly which is itself nothing but a thin wrapper over the relevant , hardware functions, interrupts. I have some very similar code for the console.

    *shrug*

    The point is that you can go as near the metal as you want without really every finding much assembly. As often as not, the assembly code you'll actually find is exactly as much as is absolutely necessary to speak directly to the hardware such as the above referenced functions doing nothing other than triggering a single interrupt.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  9. #9
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Well, everything ends up as a 2D array of pixels anyways.

  10. #10
    Registered User
    Join Date
    Nov 2013
    Posts
    107
    I think I am getting some of this. The (simplistic) way I see it is, you have a frame buffer(memory on the GPU) this is the final stage before the data is sent to the screen.

    The FB will have a predefined size, newer cards will be able to hold enough addresses for every pixel on a 4K screen for example.

    Now I assume that LCD displays are similar to CRT screens in the sense that they draw pixels in some kind of linear order, CRT's scan from left to right, top to bottom at the speed of the refresh rate.

    Now all the frame buffer will contain are RGBA values, and these values need to be in the correct order with respective to the scan order of the screen.

    I can visualise that, to a degree, however, we go from keyboard input/compilation to memory and inbetween we have BIOS, CPU and GPU and these magic memory mapped addresses.

    So can someone paint a picture from input to screen taking into account all these aspects I have mentioned.

  11. #11
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    That's all correct. The process of inputs (points, triangles, colors, textures, etc.) to screen, whether 3D gfx or vector-based gfx, is complex and nowadays is hidden behind APIs like Cairo and/or GPU compiled shader languages like GLSL. If you're talking about writing directly to the frame buffer, that's done by the renderer -- the last stage in gfx pipeline.

    I doubt its even possible anymore to write directly to the video frame buffer on a modern OS, and even if it was, its not practical anymore.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by MacNilly View Post
    I doubt its even possible anymore to write directly to the video frame buffer on a modern OS, and even if it was, its not practical anymore.
    It is, if you write a driver. In kernel mode, you have access to absolutely everything. But as you say, it's not practical. It's extremely complex.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    So can someone paint a picture from input to screen taking into account all these aspects I have mentioned.
    O_o

    You've made some mistakes in following the earlier posts.

    The BIOS VGA mode is a relic of the old days. You can't even use the BIOS VGA mode directly in Protected Mode which is where virtually all modern operating systems play. As I said though, the BIOS is really just loading a thin driver for our use. The modern operating system isn't doing much more, conceptually speaking, than loading a more sophisticated driver at a simple level. However, modern operating systems owns all the hardware including the channels which are used to communicate between different bits of hardware. You usually can't touch the metal even in driver code. In other words, even the drivers use abstractions loaded for their use by the kernel.

    You could probably reduce the relationship to `hardware -> kernel -> video card driver -> GPU` for a simple view, but you really don't need to understand all the levels to develop a strong understanding of how the levels generally work. In the same way the BIOS knows enough to load a VGA driver for our use as a memory mapped frame which the video card actually implements, each step in the process follows a specific protocol to speak to the levels around the relevant step. The BIOS, simple VGA driver, and video card hardware each follow a specific protocol allowing us to pretend to communicate directly with the display via a simple buffer. The modern kernel knows how to talk to the hardware. The video card driver knows how to talk to the kernel. The OpenGL libraries, also sometimes called drivers, know how to speak to the video card driver. The details are different, but the responsibilities are similar.

    To partially return to the original question, the kernel needs some assembly written to speak with the hardware. Every layer above the kernel can use functions exposed by the kernel to communicate with the hardware. I don't wish to speculate on proprietary drivers, but a lot of drivers are available for "Windows" and "Linux" kernels which don't have a single line of assembly code. The drivers and graphics libraries ask the kernel to do the heavy lifting in much the same way we've asked the BIOS to abstract the VGA adapter for our use.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. (LFS) Linux From Scratch
    By Annonymous in forum Tech Board
    Replies: 0
    Last Post: 06-07-2012, 12:01 AM
  2. COM from Scratch
    By avagayard in forum C++ Programming
    Replies: 0
    Last Post: 12-11-2010, 10:56 PM
  3. Creating Windows App from Scratch
    By kingneb in forum C++ Programming
    Replies: 1
    Last Post: 11-10-2008, 06:21 PM
  4. Creating graphics with C++
    By earth_angel in forum C++ Programming
    Replies: 5
    Last Post: 06-02-2005, 12:20 PM
  5. Creating pixel graphics in MFC
    By Kristian25 in forum Windows Programming
    Replies: 2
    Last Post: 01-09-2003, 01:39 PM