Files
FC1/RenderDll/XRenderOGL/GLPBuffer.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

246 lines
6.1 KiB
C++

/*=============================================================================
GLPBuffer.cpp : implementation of the NVidia Pixel Buffers.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "GL_Renderer.h"
#include "GLPBuffer.h"
CPBuffer::CPBuffer( int w, int h, unsigned int mode ) : m_Width(w), m_Height(h), m_Mode(mode), m_MyDC(NULL), m_MyGLctx(NULL), m_Buffer(NULL)
{
}
CPBuffer::~CPBuffer()
{
if (m_Buffer)
{
pwglDeleteContext(m_MyGLctx);
wglReleasePbufferDCARB(m_Buffer, m_MyDC);
wglDestroyPbufferARB(m_Buffer);
}
}
// Check to see if the pbuffer was lost.
// If it was lost, destroy it and then recreate it.
void CPBuffer::mfHandleModeSwitch()
{
int lost = 0;
wglQueryPbufferARB(m_Buffer, WGL_PBUFFER_LOST_ARB, &lost);
if ( lost )
{
this->~CPBuffer();
mfInitialize();
}
}
// This function actually does the creation of the p-buffer.
// It can only be called once a window has already been created.
bool CPBuffer::mfInitialize(bool bShare)
{
HDC hdc = pwglGetCurrentDC();
HGLRC hglrc = pwglGetCurrentContext();
// Query for a suitable pixel format based on the specified mode.
int iattributes[2*MAX_ATTRIBS];
float fattributes[2*MAX_ATTRIBS];
int nfattribs = 0;
int niattribs = 0;
// Attribute arrays must be "0" terminated - for simplicity, first
// just zero-out the array entire, then fill from left to right.
for ( int a = 0; a < 2*MAX_ATTRIBS; a++ )
{
iattributes[a] = 0;
fattributes[a] = 0;
}
// Since we are trying to create a pbuffer, the pixel format we
// request (and subsequently use) must be "p-buffer capable".
iattributes[2*niattribs ] = WGL_DRAW_TO_PBUFFER_ARB;
iattributes[2*niattribs+1] = true;
niattribs++;
if (m_Mode & FPB_DRAWTOTEXTURE)
{
iattributes[2*niattribs ] = WGL_BIND_TO_TEXTURE_RGB_ARB;
iattributes[2*niattribs+1] = true;
niattribs++;
}
else
{
if ( m_Mode & FPB_INDEX )
{
iattributes[2*niattribs ] = WGL_PIXEL_TYPE_ARB;
iattributes[2*niattribs+1] = WGL_TYPE_COLORINDEX_ARB; // Yikes!
niattribs++;
}
else
{
iattributes[2*niattribs ] = WGL_PIXEL_TYPE_ARB;
iattributes[2*niattribs+1] = WGL_TYPE_RGBA_ARB;
niattribs++;
}
if ( m_Mode & FPB_DOUBLE )
{
iattributes[2*niattribs ] = WGL_DOUBLE_BUFFER_ARB;
iattributes[2*niattribs+1] = true;
niattribs++;
}
if ( m_Mode & FPB_DEPTH )
{
iattributes[2*niattribs ] = WGL_DEPTH_BITS_ARB;
iattributes[2*niattribs+1] = 1;
niattribs++;
}
if ( m_Mode & FPB_STENCIL )
{
iattributes[2*niattribs ] = WGL_STENCIL_BITS_ARB;
iattributes[2*niattribs+1] = 1;
niattribs++;
}
if ( m_Mode & FPB_ACCUM )
{
iattributes[2*niattribs ] = WGL_ACCUM_BITS_ARB;
iattributes[2*niattribs+1] = 1;
niattribs++;
}
iattributes[2*niattribs ] = WGL_SUPPORT_OPENGL_ARB;
iattributes[2*niattribs+1] = true;
niattribs++;
}
int format;
int pformat[MAX_PFORMATS];
unsigned int nformats;
if ( !wglChoosePixelFormatARB( hdc, iattributes, fattributes, MAX_PFORMATS, pformat, &nformats ) )
{
iLog->Log("Warning: PBuffer creation error: Couldn't find a suitable pixel format.\n" );
return false;
}
format = pformat[0];
// Create the p-buffer.
iattributes[0] = 0;
niattribs = 0;
if (m_Mode & FPB_DRAWTOTEXTURE)
{
iattributes[2*niattribs ] = WGL_TEXTURE_FORMAT_ARB;
iattributes[2*niattribs+1] = WGL_TEXTURE_RGBA_ARB;
niattribs++;
iattributes[2*niattribs ] = WGL_TEXTURE_TARGET_ARB;
iattributes[2*niattribs+1] = WGL_TEXTURE_2D_ARB;
niattribs++;
iattributes[2*niattribs ] = WGL_MIPMAP_TEXTURE_ARB;
iattributes[2*niattribs+1] = 0;
niattribs++;
iattributes[2*niattribs ] = WGL_PBUFFER_LARGEST_ARB;
iattributes[2*niattribs+1] = 0;
niattribs++;
iattributes[2*niattribs ] = 0;
}
m_Buffer = wglCreatePbufferARB( hdc, format, m_Width, m_Height, iattributes );
if ( !m_Buffer )
{
DWORD err = GetLastError();
iLog->Log("Warning: PBuffer creation error: wglCreatePbufferARB() failed\n" );
if ( err == ERROR_INVALID_PIXEL_FORMAT )
{
iLog->Log("Warning: ERROR_INVALID_PIXEL_FORMAT\n" );
}
else
if ( err == ERROR_NO_SYSTEM_RESOURCES )
{
iLog->Log("Warning: ERROR_NO_SYSTEM_RESOURCES\n" );
}
else
if ( err == ERROR_INVALID_DATA )
{
iLog->Log("Warning: ERROR_INVALID_DATA\n" );
}
return false;
}
// Get the device context.
m_MyDC = wglGetPbufferDCARB( m_Buffer );
if ( !m_MyDC )
{
iLog->Log("Warning: PBuffer creation error: wglGetPbufferDCARB() failed\n" );
return false;
}
// Create a gl context for the p-buffer.
m_MyGLctx = pwglCreateContext( m_MyDC );
if ( !m_MyGLctx )
{
iLog->Log("Warning: PBuffer creation error: wglCreateContext() failed\n" );
return false;
}
if( bShare )
{
if( !pwglShareLists(hglrc, m_MyGLctx) )
{
iLog->Log("Warning: PBuffer: wglShareLists() failed\n" );
return false;
}
}
// Determine the actual width and height we were able to create.
wglQueryPbufferARB( m_Buffer, WGL_PBUFFER_WIDTH_ARB, &m_Width );
wglQueryPbufferARB( m_Buffer, WGL_PBUFFER_HEIGHT_ARB, &m_Height );
#ifdef _DEBUG
iLog->Log("Created a %d x %d PBuffer\n", m_Width, m_Height );
#endif
return true;
}
bool CPBuffer::mfMakeCurrent()
{
if ( !pwglMakeCurrent( m_MyDC, m_MyGLctx ) )
{
iLog->Log("Warning: CPBuffer::mfMakeCurrent() failed.\n" );
return false;
}
return true;
}
bool CPBuffer::mfMakeMainCurrent()
{
CGLRenderer *rd = gcpOGL;
if ( !pwglMakeCurrent( rd->m_CurrContext->m_hDC, rd->m_CurrContext->m_hRC ) )
{
iLog->Log("Warning: CPBuffer::mfMakeMainCurrent() failed.\n" );
return false;
}
return true;
}
BOOL CPBuffer::mfTextureBind()
{
return wglBindTexImageARB(m_Buffer, WGL_FRONT_LEFT_ARB);
}
BOOL CPBuffer::mfReleaseFromTexture()
{
return wglReleaseTexImageARB(m_Buffer, WGL_FRONT_LEFT_ARB);
}