remove use of opengl context for window final surface, force child window option on context

This commit is contained in:
Christopher Lloyd 2012-01-07 23:32:37 -05:00
parent 568e8143c2
commit 77beebf4ef
4 changed files with 107 additions and 32 deletions

View File

@ -54,6 +54,7 @@ struct _CGLContextObj {
int x,y;
int w,h;
GLint opacity;
GLint forceChildWindow;
GLint hidden;
GLint inParent;
CGLPixelSurface *overlay;
@ -89,9 +90,23 @@ static LRESULT CALLBACK windowProcedure(HWND handle,UINT message,WPARAM wParam,L
if(message==WM_PAINT){
Win32Window *parentWindow=GetProp(handle,"Win32Window");
#if 0
ValidateRect(handle, NULL);
return [parentWindow WM_APP1_wParam:wParam lParam:lParam];
#else
PAINTSTRUCT paintStruct;
RECT updateRECT;
GetWindowRect(handle,&updateRECT);
InvalidateRect(handle,&updateRECT,FALSE);
if(GetUpdateRect(handle,&updateRECT,NO)){
BeginPaint(handle,&paintStruct);
[parentWindow WM_APP1_wParam:wParam lParam:lParam];
EndPaint(handle,&paintStruct);
}
#endif
return 0;
}
if(message==WM_SETCURSOR){
@ -121,12 +136,6 @@ static LRESULT CALLBACK windowProcedure(HWND handle,UINT message,WPARAM wParam,L
*/
CRITICAL_SECTION requestCriticalSection;
static void createWindowForContext(CGLContextObj context){
context->parent=CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE,"CGLWindow","",WS_POPUP|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,0,0,10,10,NULL,NULL,GetModuleHandle(NULL),NULL);
context->window=CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE,"CGLWindow","",WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,0,0,context->w,context->h,context->parent,NULL,GetModuleHandle(NULL),NULL);
}
static void initializeRequest(){
InitializeCriticalSection(&requestCriticalSection);
}
@ -181,22 +190,6 @@ static int reportGLErrorIfNeeded(const char *function,int line){
return error;
}
#if 0
static BOOL contextHasMakeCurrentReadExtension(CGLContextObj context){
const char *extensions=opengl_wglGetExtensionsStringARB(context->windowDC);
reportGLErrorIfNeeded(__PRETTY_FUNCTION__,__LINE__);
if(extensions==NULL)
return NO;
if(strstr(extensions,"WGL_ARB_make_current_read")==NULL)
return NO;
return YES;
}
#endif
static void _CGLCreateDynamicPbufferBacking(CGLContextObj context);
static void _CGLDestroyDynamicPbufferBacking(CGLContextObj context);
CGLError _CGLSetCurrentContextFromThreadLocal(int value);
@ -322,7 +315,10 @@ static void pfdFromPixelFormat(PIXELFORMATDESCRIPTOR *pfd,CGLPixelFormatObj pixe
/* It has to be double buffered regardless of what the application asks for, because we're reading from it, all the pixels must be
valid. A single buffer context is problematic in that the driver may not render obscured pixels, all of them since it is off-screen.
That isnt a problem with pbuffers but this is the fallback. */
#ifndef PFD_SUPPORT_COMPOSITION
#define PFD_SUPPORT_COMPOSITION 0x00008000
#endif
pfd->dwFlags=PFD_SUPPORT_OPENGL|PFD_DRAW_TO_WINDOW|PFD_DOUBLEBUFFER;
pfd->iLayerType=PFD_MAIN_PLANE;
pfd->iPixelType=PFD_TYPE_RGBA;
@ -372,7 +368,7 @@ return;
static BOOL contextHasPbufferExtension(CGLContextObj context){
const char *extensions=opengl_wglGetExtensionsStringARB(context->windowDC);
// NSLog(@"extensions=%s",extensions);
reportGLErrorIfNeeded(__PRETTY_FUNCTION__,__LINE__);
@ -472,7 +468,10 @@ CGL_EXPORT CGLError CGLCreateContext(CGLPixelFormatObj pixelFormat,CGLContextObj
context->w=64;
context->h=64;
createWindowForContext(context);
context->forceChildWindow = TRUE;
context->parent=CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE,"CGLWindow","",WS_POPUP|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,0,0,10,10,NULL,NULL,GetModuleHandle(NULL),NULL);
context->window=CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE,"CGLWindow","",WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,0,0,context->w,context->h,context->parent,NULL,GetModuleHandle(NULL),NULL);
context->windowDC=GetDC(context->window);
@ -573,6 +572,9 @@ CGL_EXPORT CGLError CGLUnlockContext(CGLContextObj context) {
}
static BOOL usesChildWindow(CGLContextObj context){
if(context->forceChildWindow)
return YES;
Win32Window *parentWindow=[CGWindow windowWithWindowNumber:context->parentWindowNumber];
if(parentWindow==nil)
@ -581,7 +583,7 @@ static BOOL usesChildWindow(CGLContextObj context){
if([parentWindow isLayeredWindow])
return NO;
return YES;
return NO;
}
static BOOL shouldPutChildInParent(CGLContextObj context) {
@ -645,6 +647,13 @@ CGL_EXPORT CGLError CGLSetParameter(CGLContextObj context,CGLContextParameter pa
}
break;
case kCGLCPSurfaceIsChildWindow:
if(context->forceChildWindow!=value[0]){
context->forceChildWindow=value[0];
reflectChildWindowState(context,YES);
}
break;
case kCGLCPSurfaceBackingOrigin:;
BOOL originChanged=(context->x!=value[0] || context->y!=value[1])?YES:NO;
@ -702,6 +711,10 @@ CGL_EXPORT CGLError CGLGetParameter(CGLContextObj context,CGLContextParameter pa
value[1]=context->h;
break;
case kCGLCPSurfaceIsChildWindow:
*value=context->forceChildWindow;
break;
case kCGLCPSurfaceBackingOrigin:
value[0]=context->x;
value[1]=context->y;
@ -786,7 +799,8 @@ CGL_EXPORT CGLError CGLCopyPixels(CGLContextObj source,CGLContextObj destination
CGLError CGLFlushDrawable(CGLContextObj context) {
if(usesChildWindow(context)){
SwapBuffers(context->windowDC);
if(!SwapBuffers(context->windowDC))
NSLog(@"SwapBuffers failed, error = %d", GetLastError());
}
else {
Win32Window *parentWindow=[CGWindow windowWithWindowNumber:context->parentWindowNumber];

View File

@ -43,7 +43,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
int _textureIdCount;
GLint *_textureIds;
CGLContextObj _overlayResult;
O2Surface_DIBSection *_overlayResult;
NSMutableArray *_overlays;
int _disableFlushWindow;

View File

@ -240,7 +240,7 @@ static const char *Win32ClassNameForStyleMask(unsigned styleMask,bool hasShadow)
NSZoneFree(NULL,_surfaces);
if(_textureIds!=NULL)
NSZoneFree(NULL,_textureIds);
CGLReleaseContext(_overlayResult);
[_overlayResult release];
if(_hglrc!=NULL)
opengl_wglDeleteContext(_hglrc);
@ -500,7 +500,64 @@ CGL_EXPORT CGLError CGLCopyPixels(CGLContextObj source,CGLContextObj destination
if(_surfaceCount==0)
return backingSurface;
#if 1
int resultWidth=O2ImageGetWidth(backingSurface);
int resultHeight=O2ImageGetHeight(backingSurface);
if(O2ImageGetWidth(_overlayResult)!=resultWidth || O2ImageGetHeight(_overlayResult)!=resultHeight){
[_overlayResult release];
_overlayResult=[[O2Surface_DIBSection alloc] initWithWidth:resultWidth height:resultHeight compatibleWithDeviceContext:nil];
}
BLENDFUNCTION blend;
blend.BlendOp=AC_SRC_OVER;
blend.BlendFlags=0;
blend.SourceConstantAlpha=255;
blend.AlphaFormat=0;
O2SurfaceLock(_overlayResult);
O2SurfaceLock(backingSurface);
AlphaBlend([[_overlayResult deviceContext] dc],0,0,resultWidth,resultHeight,[[backingSurface deviceContext] dc],0,0,resultWidth,resultHeight,blend);
O2SurfaceUnlock(backingSurface);
O2SurfaceUnlock(_overlayResult);
int i;
for(i=0;i<_surfaceCount;i++) {
CGLPixelSurface *overlay;
GLint sourceOrigin[2];
GLint sourceSize[2];
GLint sourceOpacity;
CGLGetParameter(_surfaces[i],kCGLCPOverlayPointer,&overlay);
CGLGetParameter(_surfaces[i],kCGLCPSurfaceBackingOrigin,sourceOrigin);
CGLGetParameter(_surfaces[i],kCGLCPSurfaceBackingSize,sourceSize);
CGLGetParameter(_surfaces[i],kCGLCPSurfaceOpacity,&sourceOpacity);
O2Surface_DIBSection *srcSurface=(O2Surface_DIBSection *)[overlay validSurface];
if(srcSurface==nil)
return kCGLNoError;
BLENDFUNCTION blend;
blend.BlendOp=AC_SRC_OVER;
blend.BlendFlags=0;
blend.SourceConstantAlpha=255;
blend.AlphaFormat=sourceOpacity?0:AC_SRC_ALPHA;
int y=resultHeight-(sourceOrigin[1]+sourceSize[1]);
O2SurfaceLock(_overlayResult);
O2SurfaceLock(srcSurface);
AlphaBlend([[_overlayResult deviceContext] dc],sourceOrigin[0],y,sourceSize[0],sourceSize[1],[[srcSurface deviceContext] dc],0,0,sourceSize[0],sourceSize[1],blend);
O2SurfaceUnlock(srcSurface);
O2SurfaceUnlock(_overlayResult);
}
return _overlayResult;
#else
if(_overlayResult==NULL){
CGLPixelFormatObj pf;
GLint novs;
@ -535,6 +592,7 @@ CGL_EXPORT CGLError CGLCopyPixels(CGLContextObj source,CGLContextObj destination
CGLGetParameter(_overlayResult,kCGLCPOverlayPointer,&pixelSurface);
return (O2Surface_DIBSection *)[pixelSurface validSurface];
#endif
}
static int reportGLErrorIfNeeded(const char *function,int line){
@ -706,7 +764,7 @@ static int reportGLErrorIfNeeded(const char *function,int line){
if(!_hasMakeCurrentRead)
_hasMakeCurrentRead=(extensions==NULL)?NO:((strstr(extensions,"WGL_EXT_make_current_read")==NULL)?NO:YES);
_hasSwapHintRect=(extensions==NULL)?NO:((strstr(extensions,"GL_WIN_swap_hint")==NULL)?NO:YES);;
_hasSwapHintRect=(extensions==NULL)?NO:((strstr(extensions,"GL_WIN_swap_hint")==NULL)?NO:YES);
}
-(void)openGLFlushBufferOnlyContext:(CGLContextObj)onlyContext {
@ -854,7 +912,7 @@ static int reportGLErrorIfNeeded(const char *function,int line){
reportGLErrorIfNeeded(__PRETTY_FUNCTION__,__LINE__);
}
opengl_wglBindTexImageARB(CGLGetPBUFFER(pBuffer),WGL_FRONT_LEFT_ARB);
opengl_wglBindTexImageARB(CGLGetPBUFFER(pBuffer),WGL_BACK_RIGHT_ARB);
reportGLErrorIfNeeded(__PRETTY_FUNCTION__,__LINE__);
GLint vertices[4*2];
@ -959,7 +1017,7 @@ static int reportGLErrorIfNeeded(const char *function,int line){
if(_hasRenderTexture) {
// This flushes the pipeline, we want to do it last before swap buffer, but not after
// swapbuffers as that is a lot slower.
opengl_wglReleaseTexImageARB(CGLGetPBUFFER(releasePbuffers[i]),WGL_FRONT_LEFT_ARB);
opengl_wglReleaseTexImageARB(CGLGetPBUFFER(releasePbuffers[i]),WGL_BACK_RIGHT_ARB);
}
CGLReleasePBuffer(releasePbuffers[i]);
@ -1162,6 +1220,7 @@ static int reportGLErrorIfNeeded(const char *function,int line){
-(int)WM_APP1_wParam:(WPARAM)wParam lParam:(LPARAM)lParam {
[_delegate platformWindow:self needsDisplayInRect:NSZeroRect];
return 0;
}
-(int)WM_PAINT_wParam:(WPARAM)wParam lParam:(LPARAM)lParam {

View File

@ -97,6 +97,8 @@ typedef enum {
kCGLCPSurfaceBackingSize=304,
// internal, do not use
kCGLCPSurfaceIsChildWindow=500,
kCGLCPOverlayPointer=502,
kCGLCPSurfaceBackingOrigin=503,