bool WindowsCursorShapeGrabber::grabPixels(const PixelFormat *pixelFormat) { HCURSOR hCursor = getHCursor(); if (hCursor == 0) { return false; } m_lastHCursor = hCursor; // Get bitmap mask ICONINFO iconInfo; if (!GetIconInfo(hCursor, &iconInfo)) { return false; } if (iconInfo.hbmMask == NULL) { return false; } bool isColorShape = (iconInfo.hbmColor != NULL); BITMAP bmMask; if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), (LPVOID)&bmMask)) { DeleteObject(iconInfo.hbmMask); return false; } if (bmMask.bmPlanes != 1 || bmMask.bmBitsPixel != 1) { DeleteObject(iconInfo.hbmMask); return false; } m_cursorShape.setHotSpot(iconInfo.xHotspot, iconInfo.yHotspot); int width = bmMask.bmWidth; int height = isColorShape ? bmMask.bmHeight : bmMask.bmHeight/2; int widthBytes = bmMask.bmWidthBytes; const FrameBuffer *pixels= m_cursorShape.getPixels(); m_cursorShape.setProperties(&Dimension(width, height), pixelFormat); std::vector<char> maskBuff(widthBytes * bmMask.bmHeight); if (maskBuff.empty()) { DeleteObject(iconInfo.hbmMask); return true; } char *mask = &maskBuff.front(); // FIXME: Use try-catch block to escape code duplication // and free resources on an error. bool result = GetBitmapBits(iconInfo.hbmMask, widthBytes * bmMask.bmHeight, mask) != 0; DeleteObject(iconInfo.hbmMask); if (!result) { return false; } // Get cursor pixels HDC screenDC = GetDC(0); if (screenDC == NULL) { return false; } Screen::BMI bmi; try { m_screen.getBMI(&bmi, screenDC); } catch (...) { return false; } bmi.bmiHeader.biBitCount = pixelFormat->bitsPerPixel; bmi.bmiHeader.biWidth = width; bmi.bmiHeader.biHeight = -height; bmi.bmiHeader.biCompression = BI_BITFIELDS; bmi.red = pixelFormat->redMax << pixelFormat->redShift; bmi.green = pixelFormat->greenMax << pixelFormat->greenShift; bmi.blue = pixelFormat->blueMax << pixelFormat->blueShift; HDC destDC = CreateCompatibleDC(NULL); if (destDC == NULL) { DeleteDC(screenDC); return false; } void *buffer; HBITMAP hbmDIB = CreateDIBSection(destDC, (BITMAPINFO *) &bmi, DIB_RGB_COLORS, &buffer, NULL, NULL); if (hbmDIB == 0) { DeleteDC(destDC); DeleteDC(screenDC); return false; } HBITMAP hbmOld = (HBITMAP)SelectObject(destDC, hbmDIB); result = DrawIconEx(destDC, 0, 0, hCursor, 0, 0, 0, NULL, DI_IMAGE) != 0; memcpy(pixels->getBuffer(), buffer, pixels->getBufferSize()); if (!isColorShape) { WinCursorShapeUtils::winMonoShapeToRfb(pixels, mask, mask + widthBytes * height); } else { if (pixels->getBitsPerPixel() == 32) { if (WinCursorShapeUtils::winColorShapeToRfb<UINT32>(pixels, mask)) { // If the alpha channel is presented. WinCursorShapeUtils::fixAlphaChannel(pixels, mask, false); } } else if (pixels->getBitsPerPixel() == 16) { WinCursorShapeUtils::winColorShapeToRfb<UINT16>(pixels, mask); } } m_cursorShape.assignMaskFromWindows(mask); SelectObject(destDC, hbmOld); DeleteObject(hbmDIB); DeleteDC(destDC); DeleteDC(screenDC); return result; }
/** * Function for initialization. */ GLUSboolean init(GLUSvoid) { try { RequreExtentions(); // this shows how to append with transform feedback // std::cout << std::endl; std::cout << "begin append test sample" << std::endl; { const int N = 10; float data[N] = {0,1,2,3,4,5,6,7,8,9}; float data2[N] = {10,11,12,13,14,15,16,17,18,19}; int mask[N] = {0,0,0,1,1,0,0,0,1,0}; SharedBuffer dataBuff(data, N*sizeof(float)); SharedBuffer maskBuff(mask, N*sizeof(int)); SharedBuffer resBuff(data2, N*sizeof(float)); // (1) Create and relink(!!!) program // ShaderProgram appendProg("../main/Append.vert", "../main/Append.geom", "../main/Append.frag"); // set output name and relink shader. Please note this step is very important!!!!!!!!!!! // const GLchar* names[1] = {"outData"}; glTransformFeedbackVaryings (appendProg.program, 1, names, GL_SEPARATE_ATTRIBS); CHECK_GL_ERRORS; if(!appendProg.Link()) std::cerr << "can not relink program after glTransformFeedbackVaryings" << std::endl; // create input VAO // int dataLoc = glGetAttribLocation(appendProg.program, "vertex"); int maskLoc = glGetAttribLocation(appendProg.program, "inMask"); GLuint sourceVAO = CreateVAOForSpecialCase_Data1fAndMask1i(dataBuff.mapToGL(), maskBuff.mapToGL(), dataLoc, maskLoc); // do append // GLuint query; { glGenQueries(1, &query); glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query); // Then, right before calling glBeginTransformFeedback, you have to tell OpenGL to keep track of the amount of primitives written AppendDataWithProgramFromVAO(sourceVAO, resBuff.mapToGL(), N, appendProg.program); glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); } // this tells how many primitives were written // GLuint dataWritten = 0; glGetQueryObjectuiv(query, GL_QUERY_RESULT, &dataWritten); // // const float* resData = (const float*)resBuff.mapToCPUForRead(); // generate performance warning - for this case it is fine std::cout << std::endl; std::cout << "written numbers : " << dataWritten << std::endl; for(int i=0;i<dataWritten;i++) std::cout << resData[i] << " "; std::cout << std::endl; glDeleteVertexArrays(1, &sourceVAO); CHECK_GL_ERRORS; } std::cout << "end append test sample" << std::endl; std::cout << std::endl; // and here should be the test with append and OpenGL // return GLUS_TRUE; } catch(std::runtime_error e) { std::cerr << e.what() << std::endl; exit(-1); } catch(...) { std::cerr << "Unexpected Exception (init)!" << std::endl; exit(-1); } }