diff options
Diffstat (limited to 'xorg-server/hw/xwin/glx/simpledib.c')
-rw-r--r-- | xorg-server/hw/xwin/glx/simpledib.c | 675 |
1 files changed, 675 insertions, 0 deletions
diff --git a/xorg-server/hw/xwin/glx/simpledib.c b/xorg-server/hw/xwin/glx/simpledib.c new file mode 100644 index 000000000..f491e2857 --- /dev/null +++ b/xorg-server/hw/xwin/glx/simpledib.c @@ -0,0 +1,675 @@ +/* +** Simple example of rendering to a Windows DIB (Device Independent Bitmap) +*/ +#include <windows.h> +#include <math.h> +#include <GL/gl.h> + +#if !defined(M_PI) +#define M_PI 3.14159265F +#endif + +char *className = "OpenGL"; +char *windowName = "Simple DIB Example"; +int winX = 0, winY = 0; +int winWidth = 1024, winHeight = 1024; + +HDC hDC; +HDC hDCFrontBuffer; +HGLRC hGLRC; +HPALETTE hPalette; +HBITMAP hBitmap, hOldBitmap; + +void (*idleFunc)(void); + +BOOL colorIndexMode = FALSE; +BOOL doubleBuffered = FALSE; +BOOL renderToDIB = TRUE; + +/* Struct used to manage color ramps */ +struct colorIndexState { + GLfloat amb[3]; /* ambient color / bottom of ramp */ + GLfloat diff[3]; /* diffuse color / middle of ramp */ + GLfloat spec[3]; /* specular color / top of ramp */ + GLfloat ratio; /* ratio of diffuse to specular in ramp */ + GLint indexes[3]; /* where ramp was placed in palette */ +}; + +/* +** Each entry in this array corresponds to a color ramp in the +** palette. The indexes member of each struct is updated to +** reflect the placement of the color ramp in the palette. +*/ +#define NUM_COLORS (sizeof(colors) / sizeof(colors[0])) +struct colorIndexState colors[] = { + { + { 0.0F, 0.0F, 0.0F }, + { 0.1F, 0.6F, 0.3F }, + { 1.0F, 1.0F, 1.0F }, + 0.75F, { 0, 0, 0 }, + }, + { + { 0.0F, 0.0F, 0.0F }, + { 0.0F, 0.2F, 0.5F }, + { 1.0F, 1.0F, 1.0F }, + + 0.75F, { 0, 0, 0 }, + }, + { + { 0.0F, 0.05F, 0.05F }, + { 0.6F, 0.0F, 0.8F }, + { 1.0F, 1.0F, 1.0F }, + 0.75F, { 0, 0, 0 }, + }, +}; + +void +drawTorus(void) +{ + int numMajor = 32; + int numMinor = 24; + float majorRadius = 0.6F; + float minorRadius = 0.2F; + double majorStep = 2.0F*M_PI / numMajor; + double minorStep = 2.0F*M_PI / numMinor; + int i, j; + + for (i=0; i<numMajor; ++i) { + double a0 = i * majorStep; + double a1 = a0 + majorStep; + GLfloat x0 = (GLfloat) cos(a0); + GLfloat y0 = (GLfloat) sin(a0); + GLfloat x1 = (GLfloat) cos(a1); + GLfloat y1 = (GLfloat) sin(a1); + + if (i & 1) { + glColor3fv(colors[0].diff); + glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[0].indexes); + } else { + glColor3fv(colors[1].diff); + glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[1].indexes); + } + + glBegin(GL_TRIANGLE_STRIP); + for (j=0; j<=numMinor; ++j) { + double b = j * minorStep; + GLfloat c = (GLfloat) cos(b); + GLfloat r = minorRadius * c + majorRadius; + GLfloat z = minorRadius * (GLfloat) sin(b); + + glNormal3f(x0*c, y0*c, z/minorRadius); + glVertex3f(x0*r, y0*r, z); + + glNormal3f(x1*c, y1*c, z/minorRadius); + glVertex3f(x1*r, y1*r, z); + } + glEnd(); + } +} + +/*****************************************************************/ + +void +setProjection(void) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + /* + ** Preserve the aspect ratio of objects in the scene. + */ + if (winWidth > winHeight) { + GLfloat aspect = (GLfloat) winWidth / (GLfloat) winHeight; + glFrustum(-0.5F*aspect, 0.5F*aspect, -0.5F, 0.5F, 1.0F, 3.0F); + } else { + GLfloat aspect = (GLfloat) winHeight / (GLfloat) winWidth; + glFrustum(-0.5F, 0.5F, -0.5F*aspect, 0.5F*aspect, 1.0F, 3.0F); + } + glMatrixMode(GL_MODELVIEW); +} + +void +init(void) +{ + GLfloat matShine = 20.00F; + GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F }; + + glClearColor(colors[2].diff[0], colors[2].diff[1], colors[2].diff[2], 1.0F); + glClearIndex((GLfloat) colors[2].indexes[1]); + + setProjection(); + glTranslatef(0.0F, 0.0F, -2.0F); + + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine); + glLightfv(GL_LIGHT0, GL_POSITION, light0Pos); + glEnable(GL_LIGHT0); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + if (!colorIndexMode) { + glEnable(GL_COLOR_MATERIAL); + } +} + +void +doRedraw(void) +{ + static GLfloat x, y, z; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(x, 1.0F, 0.0F, 0.0F); + glRotatef(y, 0.0F, 1.0F, 0.0F); + glRotatef(z, 0.0F, 0.0F, 1.0F); + + drawTorus(); + + glPopMatrix(); + + if (renderToDIB) { + glFinish(); + BitBlt(hDCFrontBuffer, /*winWidth/4, winHeight/4, winWidth/2, winHeight/2,*/0,0,winWidth, winHeight, hDC, 0, 0, SRCCOPY); + GdiFlush(); + } else { + SwapBuffers(hDC); + } + + x += 5.0F; + if (x > 360.0F) x -= 360.0F; + y += 7.0F; + if (y > 360.0F) y -= 360.0F; + z += 9.0F; + if (z > 360.0F) z -= 360.0F; +} + +void +redraw(void) +{ + idleFunc = doRedraw; +} + +void +resize(void) +{ + setProjection(); + glViewport(0, 0, winWidth, winHeight /*winWidth/2, winHeight/2*/); +} + +/*****************************************************************/ + +void +setupDIB(HDC hDC) +{ + BITMAPINFO *bmInfo; + BITMAPINFOHEADER *bmHeader; + UINT usage; + VOID *base; + int bmiSize; + int bitsPerPixel; + + bmiSize = sizeof(*bmInfo); + bitsPerPixel = GetDeviceCaps(hDC, BITSPIXEL); + + switch (bitsPerPixel) { + case 8: + /* bmiColors is 256 WORD palette indices */ + bmiSize += (256 * sizeof(WORD)) - sizeof(RGBQUAD); + break; + case 16: + /* bmiColors is 3 WORD component masks */ + bmiSize += (3 * sizeof(DWORD)) - sizeof(RGBQUAD); + break; + case 24: + case 32: + default: + /* bmiColors not used */ + break; + } + + bmInfo = (BITMAPINFO *) calloc(1, bmiSize); + bmHeader = &bmInfo->bmiHeader; + + bmHeader->biSize = sizeof(*bmHeader); + bmHeader->biWidth = winWidth /* /2 */; + bmHeader->biHeight = winHeight /* /2 */; + bmHeader->biPlanes = 1; /* must be 1 */ + bmHeader->biBitCount = bitsPerPixel; + bmHeader->biXPelsPerMeter = 0; + bmHeader->biYPelsPerMeter = 0; + bmHeader->biClrUsed = 0; /* all are used */ + bmHeader->biClrImportant = 0; /* all are important */ + + switch (bitsPerPixel) { + case 8: + bmHeader->biCompression = BI_RGB; + bmHeader->biSizeImage = 0; + usage = DIB_PAL_COLORS; + /* bmiColors is 256 WORD palette indices */ + { + WORD *palIndex = (WORD *) &bmInfo->bmiColors[0]; + int i; + + for (i=0; i<256; i++) { + palIndex[i] = i; + } + } + break; + case 16: + bmHeader->biCompression = BI_RGB; + bmHeader->biSizeImage = 0; + usage = DIB_RGB_COLORS; + /* bmiColors is 3 WORD component masks */ + { + DWORD *compMask = (DWORD *) &bmInfo->bmiColors[0]; + + compMask[0] = 0xF800; + compMask[1] = 0x07E0; + compMask[2] = 0x001F; + } + break; + case 24: + case 32: + default: + bmHeader->biCompression = BI_RGB; + bmHeader->biSizeImage = 0; + usage = DIB_RGB_COLORS; + /* bmiColors not used */ + break; + } + + hBitmap = CreateDIBSection(hDC, bmInfo, usage, &base, NULL, 0); + if (hBitmap == NULL) { + (void) MessageBox(WindowFromDC(hDC), + "Failed to create DIBSection.", + "OpenGL application error", + MB_ICONERROR | MB_OK); + exit(1); + } + + hOldBitmap = SelectObject(hDC, hBitmap); + + free(bmInfo); +} + +void +resizeDIB(HDC hDC) +{ + SelectObject(hDC, hOldBitmap); + DeleteObject(hBitmap); + setupDIB(hDC); +} + +void +setupPalette(HDC hDC) +{ + PIXELFORMATDESCRIPTOR pfd; + LOGPALETTE* pPal; + int pixelFormat = GetPixelFormat(hDC); + int paletteSize; + + DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + /* + ** Determine if a palette is needed and if so what size. + */ + if (pfd.dwFlags & PFD_NEED_PALETTE) { + paletteSize = 1 << pfd.cColorBits; + } else if (pfd.iPixelType == PFD_TYPE_COLORINDEX) { + paletteSize = 4096; + } else { + return; + } + + pPal = (LOGPALETTE*) + malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); + pPal->palVersion = 0x300; + pPal->palNumEntries = paletteSize; + + if (pfd.iPixelType == PFD_TYPE_RGBA) { + /* + ** Fill the logical paletee with RGB color ramps + */ + int redMask = (1 << pfd.cRedBits) - 1; + int greenMask = (1 << pfd.cGreenBits) - 1; + int blueMask = (1 << pfd.cBlueBits) - 1; + int i; + + for (i=0; i<paletteSize; ++i) { + pPal->palPalEntry[i].peRed = + (((i >> pfd.cRedShift) & redMask) * 255) / redMask; + pPal->palPalEntry[i].peGreen = + (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; + pPal->palPalEntry[i].peBlue = + (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; + pPal->palPalEntry[i].peFlags = 0; + } + } else { + /* + ** Fill the logical palette with color ramps. + ** + ** Set up the logical palette so that it can be realized + ** into the system palette as an identity palette. + ** + ** 1) The default static entries should be present and at the right + ** location. The easiest way to do this is to grab them from + ** the current system palette. + ** + ** 2) All non-static entries should be initialized to unique values. + ** The easiest way to do this is to ensure that all of the non-static + ** entries have the PC_NOCOLLAPSE flag bit set. + */ + int numRamps = NUM_COLORS; + int rampSize = (paletteSize - 20) / numRamps; + int extra = (paletteSize - 20) - (numRamps * rampSize); + int i, r; + + /* + ** Initialize static entries by copying them from the + ** current system palette. + */ + GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]); + + /* + ** Fill in non-static entries with desired colors. + */ + for (r=0; r<numRamps; ++r) { + int rampBase = r * rampSize + 10; + PALETTEENTRY *pe = &pPal->palPalEntry[rampBase]; + int diffSize = (int) (rampSize * colors[r].ratio); + int specSize = rampSize - diffSize; + + for (i=0; i<rampSize; ++i) { + GLfloat *c0, *c1; + GLint a; + + if (i < diffSize) { + c0 = colors[r].amb; + c1 = colors[r].diff; + a = (i * 255) / (diffSize - 1); + } else { + c0 = colors[r].diff; + c1 = colors[r].spec; + a = ((i - diffSize) * 255) / (specSize - 1); + } + + pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]); + pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]); + pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]); + pe[i].peFlags = PC_NOCOLLAPSE; + } + + colors[r].indexes[0] = rampBase; + colors[r].indexes[1] = rampBase + (diffSize-1); + colors[r].indexes[2] = rampBase + (rampSize-1); + } + + /* + ** Initialize any remaining non-static entries. + */ + for (i=0; i<extra; ++i) { + int index = numRamps*rampSize+10+i; + PALETTEENTRY *pe = &pPal->palPalEntry[index]; + + pe->peRed = (BYTE) 0; + pe->peGreen = (BYTE) 0; + pe->peBlue = (BYTE) 0; + pe->peFlags = PC_NOCOLLAPSE; + } + } + + hPalette = CreatePalette(pPal); + free(pPal); + + if (hPalette) { + SelectPalette(hDC, hPalette, FALSE); + RealizePalette(hDC); + } +} + +void +setupPixelFormat(HDC hDC) +{ + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ + 1, /* version num */ + PFD_SUPPORT_OPENGL, /* support OpenGL */ + 0, /* pixel type */ + 0, /* 8-bit color depth */ + 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ + 0, /* no alpha buffer */ + 0, /* alpha bits (ignored) */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits (ignored) */ + 16, /* depth buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffers */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0, /* no layer, visible, damage masks */ + }; + int SelectedPixelFormat; + BOOL retVal; + + pfd.cColorBits = GetDeviceCaps(hDC, BITSPIXEL); + + if (colorIndexMode) { + pfd.iPixelType = PFD_TYPE_COLORINDEX; + } else { + pfd.iPixelType = PFD_TYPE_RGBA; + } + + if (doubleBuffered) { + pfd.dwFlags |= PFD_DOUBLEBUFFER; + } + + if (renderToDIB) { + pfd.dwFlags |= PFD_DRAW_TO_BITMAP; + } else { + pfd.dwFlags |= PFD_DRAW_TO_WINDOW; + } + + SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd); + if (SelectedPixelFormat == 0) { + (void) MessageBox(WindowFromDC(hDC), + "Failed to find acceptable pixel format.", + "OpenGL application error", + MB_ICONERROR | MB_OK); + exit(1); + } + + retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd); + if (retVal != TRUE) { + (void) MessageBox(WindowFromDC(hDC), + "Failed to set pixel format.", + "OpenGL application error", + MB_ICONERROR | MB_OK); + exit(1); + } +} + +LRESULT APIENTRY +WndProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + switch (message) { + case WM_CREATE: + return 0; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + case WM_SIZE: + if (hGLRC) { + winWidth = (int) LOWORD(lParam); + winHeight = (int) HIWORD(lParam); + /**/ + if (renderToDIB) { + resizeDIB(hDC); + } + /**/ + resize(); + return 0; + } + case WM_PALETTECHANGED: + /* + ** Update palette mapping if this *is not* the active window. + */ + if (hGLRC && hPalette && (HWND) wParam != hWnd) { + UnrealizeObject(hPalette); + SelectPalette(hDC, hPalette, FALSE); + RealizePalette(hDC); + redraw(); + return 0; + } + break; + case WM_QUERYNEWPALETTE: + /* + ** Update palette mapping if this *is* the active window. + */ + if (hGLRC && hPalette) { + UnrealizeObject(hPalette); + SelectPalette(hDC, hPalette, FALSE); + RealizePalette(hDC); + redraw(); + return TRUE; + } + break; + case WM_PAINT: + /* + ** Update the window. Don't use the device context returned by + ** BeginPaint as it won't have the right palette selected into it. + */ + if (hGLRC) { + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + redraw(); + EndPaint(hWnd, &ps); + return 0; + } + break; + case WM_CHAR: + switch ((int)wParam) { + case VK_ESCAPE: + DestroyWindow(hWnd); + return 0; + case VK_SPACE: + if (idleFunc) { + idleFunc = NULL; + } else { + idleFunc = doRedraw; + } + default: + break; + } + break; + default: + break; + } + + /* Deal with any unprocessed messages */ + return DefWindowProc(hWnd, message, wParam, lParam); +} + +int APIENTRY +WinMain( + HINSTANCE hCurrentInst, + HINSTANCE hPreviousInst, + LPSTR lpszCmdLine, + int nCmdShow) +{ + const GLubyte * Ret; + WNDCLASS wndClass; + HWND hWnd; + MSG msg; + + __asm int 3; + Ret = glGetString( GL_EXTENSIONS ); + + /* Define and register a window class */ + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = hCurrentInst; + wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = GetStockObject(WHITE_BRUSH); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = className; + RegisterClass(&wndClass); + + /* Create a window of the previously defined class */ + hWnd = CreateWindow( + className, /* Window class's name */ + windowName, /* Title bar text */ + WS_OVERLAPPEDWINDOW | /* The window's style */ + WS_CLIPCHILDREN | + WS_CLIPSIBLINGS, + winX, winY, /* Position */ + winWidth, winHeight, /* Size */ + NULL, /* Parent window's handle */ + NULL, /* Menu handle */ + hCurrentInst, /* Instance handle */ + NULL); /* No additional data */ + + /* Map the window to the screen */ + ShowWindow(hWnd, nCmdShow); + + /* Force the window to repaint itself */ + UpdateWindow(hWnd); + + /* + ** Set up for OpenGL rendering. Bind the rendering context to + ** the same device context that the palette will be selected into. + */ + hDC = GetDC(hWnd); + hDCFrontBuffer = hDC; + if (renderToDIB) { + hDC = CreateCompatibleDC(hDCFrontBuffer); + setupDIB(hDC); + } + Ret = glGetString( GL_EXTENSIONS ); + setupPixelFormat(hDC); + Ret = glGetString( GL_EXTENSIONS ); + setupPalette(hDC); + Ret = glGetString( GL_EXTENSIONS ); + hGLRC = wglCreateContext(hDC); + Ret = glGetString( GL_EXTENSIONS ); + wglMakeCurrent(hDC, hGLRC); + Ret = glGetString( GL_EXTENSIONS ); + init(); + idleFunc = doRedraw; + + + + /* Process Messages */ + while (1) { + /* execute the idle function while there are no messages to process */ + while (idleFunc && + PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE) + { + (*idleFunc)(); + } + if (GetMessage(&msg, NULL, 0, 0) != TRUE) { + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + /* + ** Finish OpenGL rendering. + */ + idleFunc = NULL; + if (hGLRC) { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hGLRC); + } + ReleaseDC(hWnd, hDC); + + return msg.wParam; +} |