• Advertisement

Archived

This topic is now archived and is closed to further replies.

Fast copy from HDC to Texture

This topic is 5554 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement
Here''s the current source. It takes the 320x240 source image and copies it to a 256x256 texture.

This nets a whopping 3fps. I also need to be able to hide the source window but still be able to read the data from it. Moving it off screen or using SW_HIDE results in not being able to read the pixel information. Getting a fast copy is more important at this point though.

15fps or better would be optimal.

data is defined as BYTE size 262144.


  
GLvoid oglClass::CreateVideoTexture(HWND hWndV)
{
hVDC = GetDC(hWndV);

//copy data to texture

int cur=0;
DWORD color;

for (int l=0;l<256;l++)
for (int c=0;c<256;c++)
{
color=GetPixel(hVDC,c*1.25,l*0.93);
memcpy(&VidData[cur],&color,4);
cur=c*4+l*1024;
}

glGenTextures(1, &videoTexture); // Create 1 Texture

glBindTexture(GL_TEXTURE_2D,videoTexture); // Bind To The Blur Texture

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering


glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, VidData);

ReleaseDC(hWndV,hVDC);
}


Ben



IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]

Share this post


Link to post
Share on other sites
hmmmm, what would be the image you are trying to grab from video ram via get pixles?
I assume its one you''ve already made yourself?
if thats so then you could render it direct to a pbuffer, thus giving you the data in a texture form already to go.

Share this post


Link to post
Share on other sites
can you use 512x512 texture? it should give you much better quality.

Share this post


Link to post
Share on other sites
I could (if I ever figure out how to change the video format) but it'd probably die performance wise.

At this point I'm more concerned about making it fast. I'll make it pretty later.

click for larger image


The small picture is the original source and the larger is the copy on the texture.

Ben


IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]


[edited by - KalvinB on December 8, 2002 3:17:50 AM]

Share this post


Link to post
Share on other sites
well, believe it or not, 512x512 texture might end up being faster than your present code. i assume that your video input and gl renderer can agree on a data format.

create a temporary bitmap with dimensions 512x512, same format as the video dc''s bitmap, and get a compatible dc for it. if you kwow video dc at load time, create a dc compatible to that and create a bitmap compatible with compatible dc (as opposed to using CreateDIBSection()). select bitmap into compatible dc. all of this is done on load. also, keep a pointer to bitmap bits around.

every frame, call BitBlt() and transfer 320x240 image from your video dc to the temporary dc. don''t scale anything. call GdiFlush().

use glteximage2d for the entire 512x512 bitmap. in other words, upload entire 512x512 bitmap to opengl. you should only need one gl call for this.

then you''ll have to modify your texcoords to only reference 320x240 part of the 512x512 texture. i suppose you can do this?

Share this post


Link to post
Share on other sites

  
hVDC = GetDC(hWndV);

HDC hBDC=CreateCompatibleDC (NULL);
HBITMAP hBmp = CreateCompatibleBitmap( hBDC, 256,256);
which=BitBlt(hBDC,0,0,100,100,hVDC,0,0,NULL);
GdiFlush();
SelectObject( hBDC, hBmp );

BITMAP BM;
::GetObject (hBmp, sizeof (BM), &BM);


"which" is comming back true so BM.bmBits is being copied to the texture instead of the pixel by pixel copy. However nothing is showing up.

When I tried copying the hBDC pixel by pixel it was empty.

Ben


IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]

Share this post


Link to post
Share on other sites
hey niyaw, post the solution. Oh, I forgot, you''re all talk and no walk.

Kuphryn

Share this post


Link to post
Share on other sites
quote:
Original post by KalvinB
Moving the select had no noticable effect since no data is being copied to hBDC anyway.


device contexts come with 1x1 bitmaps selected into them, which is why your present code, even when used with srccopy gives the impression that nothing is copied. using 0 for raster op may mean that you''re requesting windows to do nothing. (at least none of ternary raster ops in wingdi.h are 0.)

you say that selecting your bitmap into bitmap dc before blitting and using srccopy together still gives you no sensible image in bitmap dc?

Share this post


Link to post
Share on other sites

  
GLvoid oglClass::CreateVideoTexture(HWND hWndV)
{
HDC hDC, // Handle to the display device context

hDCMem; // Handle to the memory device context

HBITMAP hBitmap, // Handle to the new bitmap

hOldBitmap; // Handle to the old bitmap

BITMAP bm;
int iWidth, iHeight; // Width and height of the bitmap

char str[256];

hDC = GetDC (hWndV);
hDCMem = CreateCompatibleDC (hDC);

iWidth=320;
iHeight=240;
hBitmap = CreateCompatibleBitmap (hDC, 512, 512);
SelectObject (hDCMem, hBitmap);
BitBlt (hDCMem, 0, 0, iWidth, iHeight, hDC, 0, 0, SRCCOPY);
SelectObject (hDC, hBitmap);
int bytes=GetObject(hBitmap, sizeof(BITMAP), &bm);
if(bytes==0)
MessageBox(NULL,"failed","GetObjectFailed",MB_OK|MB_ICONEXCLAMATION);
else
{
sprintf(str,"%d, %d, %d",bytes, sizeof(bm), bm.bmBits);
MessageBox(NULL,str,"GetObjectFailed",MB_OK|MB_ICONEXCLAMATION);

}

if(bm.bmBits!=NULL)
{
memcpy (str, bm.bmBits, 100);
MessageBox(NULL,str,"Stuff",MB_OK|MB_ICONEXCLAMATION);
}

glBindTexture(GL_TEXTURE_2D,videoTexture); // Bind To The Video Texture

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering


glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, bm.bmBits);

// Delete the bitmap object and free all resources associated with it.

DeleteObject (hBitmap);

// Delete the memory device context and the display device context.

DeleteDC (hDCMem);
DeleteDC (hDC);

}


The image is now successfully copied to the temporary HDC however it''s refusing to go into a BITMAP. bm.bmBits is null even though all the other variables in the struct are accurate.

Ben


IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]

Share this post


Link to post
Share on other sites
1: bitmap may only be selected in one dc at a time.

2: save return value of your selectobject() calls, and select original bitmaps back into the dc when you''re done. you can''t delete a bitmap while it''s selected into a dc.

3: why are you selecting bitmap into window dc?

4: create temporary dc and compatible bitmap on load time, not every frame. also move getobject call to where your bitmap is created.

Share this post


Link to post
Share on other sites
for what exactly?

edit: i can try to fix your existing code, but surely you don't expect me to code a video to texture renderer from scratch?

[edited by - niyaw on December 8, 2002 5:06:01 PM]

Share this post


Link to post
Share on other sites
"surely you don''t expect me to code a video to texture renderer from scratch"

Of course not. That part works as I showed with the screenshot. The part I''m asking about is simply getting the data from the HDC to bm.bmBits.

You''re tossing out what to do but it makes no sense. If you could post actual working source, that''d be great.

Ben


IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]

Share this post


Link to post
Share on other sites
try this.

      
GLvoid oglClass::CreateVideoTexture(HWND hWndV)
{
HDC hDC, // Handle to the display device context

hDCMem; // Handle to the memory device context

HBITMAP hBitmap, // Handle to the new bitmap

hOldBitmap; // Handle to the old bitmap

BITMAP bm;
int iWidth, iHeight; // Width and height of the bitmap

char str[256];

// this should be done on init

// do you have control over window? if yes, use CS_OWNDC class style and keep this code

// if no, we need something else

hDC = GetDC (hWndV);
hDCMem = CreateCompatibleDC (hDC);
hBitmap = CreateCompatibleBitmap (hDCMem, 512, 512);
iWidth=320;
iHeight=240;
int bytes=GetObject(hBitmap, sizeof(BITMAP), &bm);
HGDIOBJ OldBitmap = SelectObject (hDCMem, hBitmap);

// this should be done every frame

BitBlt (hDCMem, 0, 0, iWidth, iHeight, hDC, 0, 0, SRCCOPY);
GdiFlush();

glBindTexture(GL_TEXTURE_2D,videoTexture); // Bind To The Video Texture

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering


glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, bm.bmBits);

// this should be done on cleanup

SelectObject(hDCMem, OldBitmap);
DeleteObject (hBitmap);
DeleteDC (hDCMem);
// don't delete hDC if you have CS_OWNDC

}



[edited by - niyaw on December 8, 2002 5:46:07 PM]

Share this post


Link to post
Share on other sites
The below works as intended but it''s only 5fps (an inprovement from 2-3 though). I just need to move everything out that doesn''t need to be done every frame.


  
GLvoid oglClass::CreateVideoTexture(HWND hWndV)
{
hVDC=GetDC(hWndV);

// Prepare to create a bitmap

BYTE* pBitmapBits;
BITMAPINFO bmi;
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)512;
bmi.bmiHeader.biHeight = -(int)512;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;

// Create and clear a DC and a bitmap for the font

HDC hFDC = CreateCompatibleDC( hVDC );

HBITMAP hbmBitmap = CreateDIBSection( hFDC, &bmi, DIB_RGB_COLORS,
(VOID**)&pBitmapBits, NULL, 0 );
SelectObject( hFDC, hbmBitmap );
SetMapMode(hFDC, GetMapMode(hVDC));
BitBlt(hFDC,0,0,320,240,hVDC,0,0,SRCCOPY);

glBindTexture(GL_TEXTURE_2D,videoTexture); // Bind To The Video Texture

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering


glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 512, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pBitmapBits);


ReleaseDC(hWndV,hVDC);
DeleteObject( hbmBitmap );
DeleteDC( hFDC );
}


Ben


IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]

Share this post


Link to post
Share on other sites
The fps was intially low because I was using GetMessage instead of PeekMessage.

Click for larger image:


This, along with the serial port communication class and GPS decoder class will be released to public domain after a bit of clean up.

It''s basically everything you need to make a GPS title.

Ben


IcarusIndie.com [ The Labyrinth | DevZone | The Wall | Hosting | Tiberian Merchandise | GameShot | Fun With Cutouts ]

Share this post


Link to post
Share on other sites

  • Advertisement