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;
}
Exemple #2
0
/**
* 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);
  }
}