// Create a new texture handle...
geRDriver_THandle *DRIVERCC THandle_Create(int32 Width, int32 Height, int32 NumMipLevels, 
										   const geRDriver_PixelFormat *PixelFormat)
{
	geRDriver_THandle	*THandle;	
	GLubyte				Log;

	
	THandle = FindTextureHandle();

	if (!THandle)
	{
		SetLastDrvError(DRV_ERROR_GENERIC, "OGL_THandleCreate: No more handles left.");
		gllog("ERROR:  OGL_THandleCreate: No more handles left.\n");
		goto ExitWithError;
	}

	if(PixelFormat->Flags & RDRIVER_PF_3D)
	{
		char errMsg[64];

		if(Width > maxTextureSize)
		{
			sprintf(errMsg, "OGL_THandleCreate: Width > GL_MAX_TEXTURE_SIZE (%d)", maxTextureSize);
			SetLastDrvError(DRV_ERROR_GENERIC, errMsg);
			gllog("%s\n", errMsg);
			goto ExitWithError;
		}

		if (Height > maxTextureSize)
		{
			sprintf(errMsg, "OGL_THandleCreate: Height > GL_MAX_TEXTURE_SIZE (%d)", maxTextureSize);
			SetLastDrvError(DRV_ERROR_GENERIC, errMsg);
			gllog("%s\n", errMsg);
			goto ExitWithError;
		}
	}

	THandle->MipLevels			= NumMipLevels;
	THandle->Width				= Width;
	THandle->Height				= Height;
	THandle->PixelFormat		= *PixelFormat;
	THandle->Flags				= 0;
	
	Log							= (uint8)GetLog(Width, Height);
	
	if(THandle->PixelFormat.Flags & RDRIVER_PF_2D)
	{
		THandle->PaddedWidth = SnapToPower2(THandle->Width);
		THandle->PaddedHeight = SnapToPower2(THandle->Height);
	}
	else if(THandle->PixelFormat.Flags & RDRIVER_PF_3D)
	{
		THandle->InvScale = 1.0f / (GLfloat)((1<<Log));
	}
	else
	{
		// Must be a lightmap
		THandle->Flags |= THANDLE_UPDATE_LM;
		THandle->InvScale = 1.0f / (GLfloat)((1<<Log)<<4);	
	}

	// Init an OpenGL texture object to hold this texture
	glGenTextures(1, &(THandle->TextureID));

	return THandle;
		
	ExitWithError:
	{
		return NULL;
	}
}
int32 GetLog(int32 Width, int32 Height)
{
	int32	LWidth = SnapToPower2(max(Width, Height));
	
	return Log2(LWidth);
}
Esempio n. 3
0
// Render a 2D decal graphic...
// Notes: unfortunately traditional thru-the-API framebuffer access for OpenGL is 
//        ridculously slow with most ICDs.
//        So I've implemented decals as clamped textures on polygons.
//        This works rather well... usually... and it is fast.  However, it has drawbacks....
//        1) Extra use of texture ram to hold decals
//        2) May look shoddy under some situations on cards with 256x256 texture maximums 
//           (3DFX Voodoo springs to mind) 
//           Reason: If they only support 256x256, large decals like the GTest bitmap font may 
//           be sampled down to 256x256 and then restreched when drawing.  I haven't tested this 
//           against such cards, due to lack of any access to one, but my guess is the resulting 
//           image wont look so hot.
//
// In the future, may want to add platform-specific framebuffer access (GDI, X11, etc) as 
// allowed.  But...for Windows, DirectDraw isn't supported, and to the best of my knowledge, 
// GDI is only reliably supported when not using a double-buffer.  Joy.
geBoolean DRIVERCC DrawDecal(geRDriver_THandle *THandle, RECT *SRect, int32 x, int32 y)
{
	RECT tmpRect, *srcRect;
	GLint width, height;
	GLfloat uClamp, vClamp;
	GLfloat uDiff = 1.0f, vDiff = 1.0f;
	
	if(!RenderingIsOK)
		return GE_TRUE;

	if(!SRect)
	{
		tmpRect.left = 0;
		tmpRect.right = THandle->Width;
		tmpRect.top = 0;
		tmpRect.bottom = THandle->Height;

		srcRect = &tmpRect;
		width = (THandle->Width);
		height = (THandle->Height);
	}
	else
	{
		srcRect = SRect;
		width = (srcRect->right - srcRect->left);
		height = (srcRect->bottom - srcRect->top);
	}
	
	if(x + width <= 0 || y + height <= 0 || x >= ClientWindow.Width || y >= ClientWindow.Height)
	{
		return GE_TRUE;
	}
	
	if(x + width >= (ClientWindow.Width - 1))
	{
		srcRect->right -= ((x + width) - (ClientWindow.Width - 1));
	}

	if(y + height >= (ClientWindow.Height - 1))
	{
		srcRect->bottom -= ((y + height) - (ClientWindow.Height - 1));
	}

	if(x < 0)
	{
		srcRect->left += -x;
		x = 0;
	}
	
	if(y < 0)
	{
		srcRect->top += -y;
		y = 0;
	}

	if(boundTexture != THandle->TextureID)
	{
		glBindTexture(GL_TEXTURE_2D, THandle->TextureID);
		boundTexture = THandle->TextureID;
	}

	if(THandle->Flags & THANDLE_UPDATE)
	{
		THandle_Update(THandle);
	}
	
	glDisable(GL_DEPTH_TEST);
	
	glColor4f(1.0, 1.0, 1.0, 1.0);
	
	glShadeModel(GL_FLAT);
	
	if(THandle->Data[1] == NULL)
	{
		uClamp = width / (GLfloat)THandle->PaddedWidth;
		vClamp = height / (GLfloat)THandle->PaddedHeight;
		
		glMatrixMode(GL_TEXTURE); 
		glPushMatrix();
		glLoadIdentity();
		glTranslatef(srcRect->left / (GLfloat)THandle->PaddedWidth, 
			srcRect->top / (GLfloat)THandle->PaddedHeight, 0.0f);
		
		glBegin(GL_QUADS);
		
		glTexCoord2f(0.0f, 0.0);
		glVertex2i(x, y);
		
		glTexCoord2f(uClamp, 0.0f);
		glVertex2i(x + width, y);
		
		glTexCoord2f(uClamp, vClamp);
		glVertex2i(x + width, y + height);
		
		glTexCoord2f(0.0f, vClamp);
		glVertex2i(x, y + height);
		
		glEnd();  
		
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
	}
	else
	{
	
		glPixelStorei(GL_UNPACK_ROW_LENGTH, THandle->Width);
		glPixelStorei(GL_UNPACK_SKIP_PIXELS, srcRect->left);
		glPixelStorei(GL_UNPACK_SKIP_ROWS, srcRect->top);

		glPixelZoom(1.0, -1.0);

		if(width <= maxTextureSize && height <= maxTextureSize &&
			width == SnapToPower2(width) && height == SnapToPower2(height))
		{
			// Last chance to avoid the dreaded glDrawPixels...Yes, this is faster
			// than glDrawPixels on the ICD's I've tested.  Go figure.
			// (Could add a more complex texture upload/clamp system for
			//  width/heights other than powers of 2, but for now,
			//  this is enough complexity...Sorry, 3DFX)

			if(decalTexObj == -1)
			{
				glGenTextures(1, &decalTexObj);
			}

			glBindTexture(GL_TEXTURE_2D, decalTexObj);
			boundTexture = decalTexObj;

			glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 
					0, GL_RGBA, GL_UNSIGNED_BYTE, THandle->Data[1]); 

			glBegin(GL_QUADS);
			
			glTexCoord2f(0.0f, 0.0);
			glVertex2i(x, y);
			
			glTexCoord2f(1.0f, 0.0f);
			glVertex2i(x + width, y);
			
			glTexCoord2f(1.0f, 1.0f);
			glVertex2i(x + width, y + height);
			
			glTexCoord2f(0.0f, 1.0f);
			glVertex2i(x, y + height);
			
			glEnd();
		}
		else
		{
			glPixelZoom(1.0, -1.0);

			glRasterPos2i(x, y);
			glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, THandle->Data[1]);
		}

		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
		glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
		glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
	} 
	
	glShadeModel(GL_SMOOTH);
	
	glEnable(GL_DEPTH_TEST); 
	
	return GE_TRUE; 
}