Getting a window's pixel format - c++

I have created an OpenGL application running on Windows. Is there any way I can query information about the pixel format of my current rendering window?
(the window was created using the GLFW library)
What I'm interested in:
Color bits
Depth bits
Pixel type
etc.

I do it like this:
int i;
HDC hdc;
PIXELFORMATDESCRIPTOR pfd;
hdc = GetDC(window_handle); // get device context
i=GetPixelFormat(hdc); // pixel format descriptor index
DescribePixelFormat(hdc,i,sizeof(pfd),&pfd); // format from index
Where window_handle is handle of your apps window. If you got access to the hdc directly than you can skip the first line GetDC. This is how I print the info using VCL and my GL engine:
scr.text(AnsiString().sprintf("color: %i bit R%i G%i B%i A%i",pfd.cColorBits,pfd.cRedBits,pfd.cGreenBits,pfd.cBlueBits,pfd.cAlphaBits));
scr.text(AnsiString().sprintf("accum: %i",pfd.cAccumBits));
scr.text(AnsiString().sprintf("depth: %i",pfd.cDepthBits));
scr.text(AnsiString().sprintf("stenc: %i",pfd.cStencilBits));
scr.text(AnsiString().sprintf("auxil: %i",pfd.cAuxBuffers));
so just use what you got at your disposal for text print. There is a bit more in the pfd structure like bit-shifts, masks etc just inspect it and print what you need.

In the GLFW doc you can read about using the OpenGL API directly by for example glGetFramebufferAttachmentParameteriv or glGetIntegerv.

You can call glfwGetWin32Window function (from glfw3native.h) and retrieve handle of window.
Get HDC form handle (with GetDC(window_handle) function) Then pass this HDC to GetPixelFormat function and call DescribePixelFormat.
See example of usage GetPixelFormat + DescribePixelFormat here:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd318349(v=vs.85).aspx

Related

OpenGL get Device Context

I am trying to create an OpenGL application on windows. As far as I can understand, one of the first things I must acquire is a Device Context, which must be passed on to a couple of functions that choose and set a pixel format and create a rendering context. I used the OpenGL wiki to get a rough idea about what I should do.
My code is something like:
#include <iostream>
#include <windef.h>
#include <wingdi.h>
HDC hdc;
int main() {
hdc = wglGetCurrentDC();
std::cout << "HDC: " << hdc << std::endl;
return 0;
}
This prints
HDC: 0
I assumed a Device Context refers to a physical device, but I read somewhere that it refers to any drawable "surface". In both cases is my question: how can I obtain a non-null DC? Or should I perform a completely different set of steps in order to set up this whole OpenGL system?
I found a lot of tutorials online, but they all use GLUT, GLEW, GLFW, X11, SDL etc. which are libraries. Libraries make certain things easier, but they usually do not perform tasks that are impossible without using them. This time, I want to try to do things the hard way and therefore use no libraries, just plain OpenGL.
I found, at last, a tutorial that only used the windows libraries for creating a window.
You did not state your OS but I assume Windows from the function names. The problem is exactly as Reto Koradi stated in the comment. To set up OpenGL you need to do this:
Obtain OS handle to object with valid device context
It can be OS window or OS bitmap. If you have just console app then you need to create a valid OS window first and use its handle (to my knowledge console does not have Canvas).
you can use GLUT for the window creation or If your compiler IDE has an window App you can use that. You can also combine OpenGL and Window components. VCL is also not a problem (I am using it for years with OpenGL)
In windows you can use CreateWindowEx so google an example for it...
Anyway you should have your handle in a variable like:
HWND hwin=NULL;
If you have no experience with windows applications then use GLUT for this. Otherwise you would need to learn a lot of stuff just to cover window creation, message handling of events and user/app interaction which can be really overwhelming for a rookie without guide.
Get Device context for that handle
HDC hdc = GetDC(hwin);
Set pixel format you need of device context
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory( &pfd, sizeof( pfd ) ); // set the pixel format for the DC
pfd.nSize = sizeof( pfd );
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
Create OpenGL rendering context for device context
HGLRC hrc = wglCreateContext(hdc);
Set it as default OpenGL context
wglMakeCurrent(hdc, hrc);
This is absolute minimum without any error checking , additional buffers etc. For more info and actual code see related QA's:
How to render an openGL frame in C++ builder? for oldstyle GL
simple complete GL+VAO/VBO+GLSL+shaders example in C++ with the new stuff
You can use GLUT for all of this. This is first hit I found by quick search:
How can I set an OpenGL display (Window created by OpenGL) to maximized?
Or follow OpenGL tutorials there are tons of them out there ...

How to color a specific pixel in windows console

I am new to c++ programming and I find it interesting and fun to learn.
Can anybody give me an idea in setting color for a specific pixel in a windows console while the color will stay permanent even the windows console is refreshed or moved.
I used Setpixel() for my recent code.Here are some code snippets assuming it inside the body of a function:
HWND myconsole = GetConsoleWindow();
HDC dc = GetDC(myconsole);
COLORREF color = RGB(255,120,120);
for(int count =0;count<100;count++)
{
SetPixel(dc,0,count,color);
}
Any idea and opinion would be a great help.Thanks!
Either you're question was unclear or you changed you're mind subsequently and decided you wanted to draw on a Win32 window, not a Win32 console window. In any case here are answers for both questions.
Drawing to a Win32 window (not a console)
You can draw to a Win32 project a number of ways (including graphics APIs like OpenGL and DirectX). The simplest way is to use Windows GDI (Graphics Device Interface) which is simply a number of functions which are part of Windows.h.
SetPixel() will draw to whichever Device Context you give it a handle to (the first argument). This handle must be to the Device Context of your main window if you wish to draw on the window (you could also give it a handle to an off-screen surface like a backbuffer).
So to get the handle to the Device Context of your main window use: GetDC(hWnd) where hWnd is a handle to your main window. The returned Device Context handle can be used in SetPixel() to draw to the window.
HDC _hWindowDC = GetDC(_hWnd);
SetPixel(_hWindowDC, _iXpos, _iYpos, _myColorRef);
If you want to draw to Device Context like you are trying to do, you need to make a Win32 Project, not a Win32 Console project.
Drawing to a Win32 console project
As mentioned in the comments, for a console project, you can only "draw" characters, not pixels. For example you could pick a screen coordinate and cout some characters like so:
COORD point;
point.X = _iX;
point.Y = _iY;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point);
cout << "Whatever";
#Cody Gray this is the snippets when i tried WriteConsoleOutput.This is not so great but maybe it can help other.. if someone can give idea and correct some logics and misconception here then it is better.. thanks
const CHAR_INFO *buffer;
CHAR_INFO buffer1;
buffer = &buffer1;
buffer1. Char. AsciiChar= '-';
buffer1.Attributes = 0x0001;
const SECURITY_ATTRIBUTES *securityAttribute;
HANDLE writeConsole= GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE readConsole = GetStdHandle(STD_INPUT_HANDLE);
COORD buffer1Size={10,10};
COORD position = { 4,4};
SMALL_RECT display ={4,4,50,50};
WriteConsoleOutput(writeConsole,buffer,buffer1Size,position,&display);

How can I draw inside two separate 3D windows within the same application on Windows using OpenGL?

I am implementing a plug-in inside a 3rd party program in C++ on Windows.
The 3rd party program has a window that displays 3D graphics using OpenGL.
However I need the plug-in to create another window that also displays 3D graphics using OpenGL.
Do I need to create a new OpenGL rendering context for my window or is there some way that I can "reuse" the OpenGL rendering context used by the 3rd party program?
I assumed that I had to create a new OpenGL rendering context and tried the following:
// create a rendering context
hglrc = wglCreateContext (hdc);
// make it the calling thread's current rendering context
wglMakeCurrent (hdc, hglrc);
However the last function failed.
Reading the documentation of wglMakeCurrent I notice that
A thread can have one current rendering context. A process can have multiple rendering contexts by means of multithreading.
Does this mean that my window need to run in a separate thread from the 3rd party program?
You didn't post error code generated by wglMakeCurrent(), so I won't be guessing the reason. It's not the binding itself, however. Sentence 'A thread can have one current rendering context' means, that new context will 'replace' the old one and become the current. I don't know why are you trying to set two contexts as current (or run another thread), but it's not the way to go. Avoid multithreading in rendering unless it's absolutely necessary.
So, answering your question:
Yes, you CAN 'reuse' OpenGL rendering context.
Why, you may ask? Rendering context is created for specific device context (HDC), which is exclusive property of each window (HWND)! How is this possible, then?!
Well, it seems somehow impossible because of function prototypes:
HWND my_window = CreateWindow(...);
HDC my_dc = GetDC(my_new_window);
//Setup pixel format for 'my_dc'...
HGLRC my_rc = wglCreateContext(my_dc);
wglMakeCurrent(my_dc, my_rc);
This really lets you think that rendering context is bound to this specific device context and valid only for it. But it's not.
The critical part is the comment (setup pixel format). Rendering context is created for specific CLASS of DCs, to be more precise: for DCs with the same pixel format. So code below is perfectly valid:
//window_1 = main window, window_2 = your window
HDC dc_1 = GetDC(window_1);
Set_pixel_format_for_dc_1(); //Usual stuff
HGLRC rc = wglCreateContext(dc_1);
wglMakeCurrent(dc_1, rc);
ultra_super_draw();
//.....
HDC dc_2 = GetDC(window_2);
//Get dc_1's PF to make sure it's compatible with rc.
int pf_index = GetPixelFormat(dc_1);
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
DescribePixelFormat(dc_1, pf_index, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
SetPixelFormat(dc_2, pf_index, &pfd);
wglMakeCurrent(dc_2, rc);
another_awesome_render();
wglMakeCurrent(NULL, NULL);
If you are still not convinced, MSDN:
wglMakeCurrent(hdc, hglrc): The hdc parameter must refer to a drawing surface supported by OpenGL. It need not be the same hdc that was passed to wglCreateContext when hglrc was created, but it must be on the same device and have the same pixel format.
I guess you are already familiar with these calls. Now, I don't know what are the conditions that your rendering must meet, but without additional requirements, I don't see any difficulties from this point:
HDC my_dc = Create_my_DC();
//...
void my_new_render
{
//Probably you want to save current binding:
HDC current_dc = wglGetCurrentDC();
HGLRC current_context = wglGetCurrentContext();
wglMakeCurrent(my_dc, current_context);
MyUltraSuperRender(...);
wglMakeCurrent(current_dc, current_context);
}
Hope this helps :)
First things first, you actually should create a separate OpenGL context for your plugin, for the simple reason that it gives you a separate state space that doesn't interfere with the main programs OpenGL context.
You misunderstood the part about multiple rendering contexts though. It's perfectly possible to have an arbitrary number of OpenGL contexts for a process. But each thread of the process can bind only one context at a time. That one binding also includes the window DC the context is bound to. It is however perfectly legal change a context binding at any time. Either you change the window a given context is bound to, or you switch the context or you do both at the same time.
So in your situation I suggest you create a custom context for your plug-in, that you use for all the windows your plug-in creates.
That your simple context "creation" code fails has one simple reason: Your window will most likely not have a pixel format descriptor set.
I suggest you use the following method to create your new windows and contexts:
/* first get hold of the HDC/HRC of the parent */
HDC parentDC = wglGetCurrentDC();
HRC parentRC = wglGetCurrentContext();
int pixelformatID = GetPixelFormat(parentDC);
/* we use the same PFD as the parent */
PIXELFORMATDESCRIPTOR pixelformat;
memset(pixelformat, 0, sizeof(pixelformat);
DescribePixelFormat(parentDC, pixelformatID, sizeof(pixelformat), &pixelformat);
/* create a window and set it's pixelformat to the parent one's */
HWND myWND = create_my_window();
HDC myDC = GetDC(myWND);
SetPixelFormat(myDC, pixelformatID, &pixelformat);
/* finally we can create a rendering context
* it doesn't matter if we create it against
* the parent or our own DC.
*/
HRC myRC = wglCreateContext(myDC);
/* we're done here... */
Now whenever your plugin wants to render something it should bind its own context, do its thing and bind the context that was bound before:
HDC prevDC = wglGetCurrentDC();
HRC prevRC = wglGetCurrentContext();
wglMakeCurrent(myDC, myRC);
/* do OpenGL stuff */
wglMakeCurrent(prevDC, prevRC);

How to draw on given bitmap handle (C++ / Win32)?

I'm writing an unmanaged Win32 C++ function that gets a handle to a bitmap, and I need to draw on it.
My problem is that to draw I need to get a device context, but when I do GetDC (NULL), it gives me a device context for the WINDOW! The parameter for GetDC () is a window handle (HWND), but I don't have a window; just a bitmap handle.
How can I draw on this bitmap? Thanks!
In addition to Pavel's answer, the "compatible with the screen" always bugged me too, but, since CreateCompatibleDC(NULL) is universally used for that purpose, I assume it is correct.
I think that the "compatible" thing is related just to DDB (the DC is set up to write on the correct DDB type for the current screen), but does not affect read/writes on DIBs.
So, to be safe, always use DIBs and not DDBs if you need to work on bitmaps that doesn't just have to go temporarily onscreen, nowadays the difference in performance is negligible. See here for more info about DIBs and DDBs.
CreateCompatibleDC() and SelectObject() your bitmap into it.
However, not every bitmap can be selected into any DC.
You might have to play with mapping mode and other options of memory DCs.
The basic win32 paradigm for drawing on a bitmap is that you select the bitmap onto a device context, after which, all drawing operations on that device context are stored in the bitmap. You then use one of the various 'blit' operations (e.g. StretchBlt) to transfer this to a display surface, which is just the device context of a window client area.
Others have provided better detail, this is just the high-level view.
Well, this is a bit outside the box.. I guess.. But I do know that Graphics can return a HDC, and Graphics take a Bitmap as an argument to its ctor . A Bitmap in turn can be created from a HBITMAP and a HPALETTE. The only problem here is that I do not know if the HPALETTE argument can be NULL.
Graphics* g;
Bitmap* bitmap;
HBITMAP _bitmap; // <- this one is yours
bitmap = Bitmap::FromHBITMAP(_bitmap, NULL);
g = new Graphics(bitmap);
HDC hdc = g->GetHDC();
// when done, call g->ReleaseHDC(hdc);
However, I would urge you to receive the HDC as an argument to your function as well.. I do not think that anyone will have a BITMAP and NOT have the DC to it.
If you're having these issues with finding a HDC to a HBITMAP, so will everyone else.

How to Convert a gdi+ Bitmap-like struct into an HDC?

How to Convert a Bitmap-like struct into an HDC?
I am now writting image processing program in c++, gdi.
If I got a HDC.
I can draw whatever I like on the HDC in gdi by the following code.
// HDC is handy.
HDC dc;
dc.DrawXXX // I can draw using gdi method.
Graphics gr(dc); // now I can also draw on the dc using gdi+ method.
My Application is based on FreeImage.
I make of fipImage. ( use data struct like Bitmap )
However if I want to draw on fipWinImage, now I have to copy fipWinImageto Bitmap, then draw on the Bitmap, and finally convert the bitmap into fipImage again, which is time comsuming and memory comsuming.
Convert fipImage to Bitmap -> Draw on the bitmap -> convert bitmap to fipWinImage
fipWinImage imagefip;
Bitmap* tempImg = new Bitmap(imagefip->GetWidth(), imagefip.GetHeigt(), PixelFormat24bppRGB); // memory comsuming is image is large
Graphics *pGr = Graphics::FromImage(tempImg);
HDC dc = pGr->GetHDC();
RECT rec;
rec.left = 0;
rec.top = 0;
rec.right = imagefip.GetWidth();
rec.bottom = imagefip.GetHeight();
fipImage.draw(dc, rec); // using stretchdibits()
pGr->ReleaseHDC(dc);
Graphics gr(tempImg);
HDC dc = gr.GetHDC(); // Get an Hdc, draw using gdi method
gr.ReleaseHDC(tempDC); //
gr.drawXXX // Draw using gdi+ method.
fipWinImage fipImg; // final result fipWinImage.
HBITMAP temp;
Color color;
tempImg->GetHBITMAP(color, &temp);
fipImg->copyFromBitmap(temp);
I want to construct a HDC directly from fipImage. and draw directly on fipWinImage
How can I do this?
First a few clarifications:
A Device Context is basically a structure that remembers things like foreground and background colors, brushes, font info, and the physical drawing surface (bitmap).
This is a handy thing, so that you don't have to keep specifying all of these things when you're doing one graphics operation after another. You can also pass all of these settings around more easily this way. That's all that a DC really is - just a collection of drawing parameters, including the surface to draw upon.
An "HDC" is just a handle (reference) to one of these structs. Being a "Handle" lets window move the struct around in memory to manage free space without your pointers to it getting messed up.
If you have access to the source code for the library you're using, examine the fipWinImage::draw(...) method. If they're using StretchDIBits, then they must get their raw bitmap data into a compatible format at some point. It's also possible that the fipWinImage class is wrapping an underlying BITMAP or DIB, etc.
The final step to getting your own HDC...
A bitmap is "SELECTED" into a device context, and can only be selected into a single DC at one time. If you can get the internal HBITMAP from fipWinImage, you can select it into another DC (assuming that it isn't still selected into another HC).
When you create a DC, windows automatically creates a 1x1 bitmap for it (since a DC must have a selected bitmap at all times). When you select in a new bitmap, you get the handle to the previously selected bitmap returned to you. Hang on to that, because you're going to need to put it back when you're done.
Hope that helps.
I don't know FreeImage, but if you can get a pointer to the actual pixel data (DIB section) out of it, you could just create a HBITMAP that shares it without having to copy the data every time.