Пример #1
0
static struct dri_swrast_renderbuffer *
swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv,
			GLboolean front)
{
    struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
    struct gl_renderbuffer *rb;
    GLuint pixel_format;

    TRACE;

    if (!xrb)
	return NULL;

    rb = &xrb->Base.Base;

    _mesa_init_renderbuffer(rb, 0);

    pixel_format = choose_pixel_format(visual);

    xrb->dPriv = dPriv;
    xrb->Base.Base.Delete = swrast_delete_renderbuffer;
    if (front) {
        rb->AllocStorage = swrast_alloc_front_storage;
    }
    else {
	rb->AllocStorage = swrast_alloc_back_storage;
    }

    switch (pixel_format) {
    case PF_A8R8G8B8:
	rb->Format = MESA_FORMAT_B8G8R8A8_UNORM;
	rb->InternalFormat = GL_RGBA;
	rb->_BaseFormat = GL_RGBA;
	xrb->bpp = 32;
	break;
    case PF_X8R8G8B8:
	rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; /* XXX */
	rb->InternalFormat = GL_RGB;
	rb->_BaseFormat = GL_RGB;
	xrb->bpp = 32;
	break;
    case PF_R5G6B5:
	rb->Format = MESA_FORMAT_B5G6R5_UNORM;
	rb->InternalFormat = GL_RGB;
	rb->_BaseFormat = GL_RGB;
	xrb->bpp = 16;
	break;
    case PF_R3G3B2:
	rb->Format = MESA_FORMAT_B2G3R3_UNORM;
	rb->InternalFormat = GL_RGB;
	rb->_BaseFormat = GL_RGB;
	xrb->bpp = 8;
	break;
    default:
	free(xrb);
	return NULL;
    }

    return xrb;
}
Пример #2
0
static struct swrast_renderbuffer *
swrast_new_renderbuffer(const struct gl_config *visual, GLboolean front)
{
    struct swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
    GLuint pixel_format;

    TRACE;

    if (!xrb)
	return NULL;

    _mesa_init_renderbuffer(&xrb->Base, 0);

    pixel_format = choose_pixel_format(visual);

    xrb->Base.Delete = swrast_delete_renderbuffer;
    if (front) {
	xrb->Base.AllocStorage = swrast_alloc_front_storage;
	swrast_set_span_funcs_front(xrb, pixel_format);
    }
    else {
	xrb->Base.AllocStorage = swrast_alloc_back_storage;
	swrast_set_span_funcs_back(xrb, pixel_format);
    }

    switch (pixel_format) {
    case PF_A8R8G8B8:
	xrb->Base.Format = MESA_FORMAT_ARGB8888;
	xrb->Base.InternalFormat = GL_RGBA;
	xrb->Base._BaseFormat = GL_RGBA;
	xrb->Base.DataType = GL_UNSIGNED_BYTE;
	xrb->bpp = 32;
	break;
    case PF_X8R8G8B8:
	xrb->Base.Format = MESA_FORMAT_ARGB8888; /* XXX */
	xrb->Base.InternalFormat = GL_RGB;
	xrb->Base._BaseFormat = GL_RGB;
	xrb->Base.DataType = GL_UNSIGNED_BYTE;
	xrb->bpp = 32;
	break;
    case PF_R5G6B5:
	xrb->Base.Format = MESA_FORMAT_RGB565;
	xrb->Base.InternalFormat = GL_RGB;
	xrb->Base._BaseFormat = GL_RGB;
	xrb->Base.DataType = GL_UNSIGNED_BYTE;
	xrb->bpp = 16;
	break;
    case PF_R3G3B2:
	xrb->Base.Format = MESA_FORMAT_RGB332;
	xrb->Base.InternalFormat = GL_RGB;
	xrb->Base._BaseFormat = GL_RGB;
	xrb->Base.DataType = GL_UNSIGNED_BYTE;
	xrb->bpp = 8;
	break;
    default:
	return NULL;
    }

    return xrb;
}
Пример #3
0
/*
 * Create a new X/Mesa visual.
 * Input:  display - X11 display
 *         visinfo - an XVisualInfo pointer
 *         rgb_flag - GL_TRUE = RGB mode,
 *                    GL_FALSE = color index mode
 *         alpha_flag - alpha buffer requested?
 *         db_flag - GL_TRUE = double-buffered,
 *                   GL_FALSE = single buffered
 *         stereo_flag - stereo visual?
 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
 *                       GL_FALSE = use an off-screen pixmap for back buffer
 *         depth_size - requested bits/depth values, or zero
 *         stencil_size - requested bits/stencil values, or zero
 *         accum_red_size - requested bits/red accum values, or zero
 *         accum_green_size - requested bits/green accum values, or zero
 *         accum_blue_size - requested bits/blue accum values, or zero
 *         accum_alpha_size - requested bits/alpha accum values, or zero
 *         num_samples - number of samples/pixel if multisampling, or zero
 *         level - visual level, usually 0
 *         visualCaveat - ala the GLX extension, usually GLX_NONE
 * Return;  a new XMesaVisual or 0 if error.
 */
PUBLIC
XMesaVisual XMesaCreateVisual( Display *display,
                               XVisualInfo * visinfo,
                               GLboolean rgb_flag,
                               GLboolean alpha_flag,
                               GLboolean db_flag,
                               GLboolean stereo_flag,
                               GLboolean ximage_flag,
                               GLint depth_size,
                               GLint stencil_size,
                               GLint accum_red_size,
                               GLint accum_green_size,
                               GLint accum_blue_size,
                               GLint accum_alpha_size,
                               GLint num_samples,
                               GLint level,
                               GLint visualCaveat )
{
   XMesaDisplay xmdpy = xmesa_init_display(display);
   XMesaVisual v;
   GLint red_bits, green_bits, blue_bits, alpha_bits;

   if (!xmdpy)
      return NULL;

   /* For debugging only */
   if (_mesa_getenv("MESA_XSYNC")) {
      /* This makes debugging X easier.
       * In your debugger, set a breakpoint on _XError to stop when an
       * X protocol error is generated.
       */
      XSynchronize( display, 1 );
   }

   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
   if (!v) {
      return NULL;
   }

   v->display = display;

   /* Save a copy of the XVisualInfo struct because the user may Xfree()
    * the struct but we may need some of the information contained in it
    * at a later time.
    */
   v->visinfo = (XVisualInfo *) malloc(sizeof(*visinfo));
   if (!v->visinfo) {
      free(v);
      return NULL;
   }
   memcpy(v->visinfo, visinfo, sizeof(*visinfo));

   v->ximage_flag = ximage_flag;

   v->mesa_visual.redMask = visinfo->red_mask;
   v->mesa_visual.greenMask = visinfo->green_mask;
   v->mesa_visual.blueMask = visinfo->blue_mask;
   v->visualID = visinfo->visualid;
   v->screen = visinfo->screen;

#if !(defined(__cplusplus) || defined(c_plusplus))
   v->visualType = xmesa_convert_from_x_visual_type(visinfo->class);
#else
   v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
#endif

   v->mesa_visual.visualRating = visualCaveat;

   if (alpha_flag)
      v->mesa_visual.alphaBits = 8;

   (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );

   {
      const int xclass = v->visualType;
      if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
         red_bits   = _mesa_bitcount(GET_REDMASK(v));
         green_bits = _mesa_bitcount(GET_GREENMASK(v));
         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
      }
      else {
         /* this is an approximation */
         int depth;
         depth = v->visinfo->depth;
         red_bits = depth / 3;
         depth -= red_bits;
         green_bits = depth / 2;
         depth -= green_bits;
         blue_bits = depth;
         alpha_bits = 0;
         assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
      }
      alpha_bits = v->mesa_visual.alphaBits;
   }

   /* initialize visual */
   {
      struct gl_config *vis = &v->mesa_visual;

      vis->rgbMode          = GL_TRUE;
      vis->doubleBufferMode = db_flag;
      vis->stereoMode       = stereo_flag;

      vis->redBits          = red_bits;
      vis->greenBits        = green_bits;
      vis->blueBits         = blue_bits;
      vis->alphaBits        = alpha_bits;
      vis->rgbBits          = red_bits + green_bits + blue_bits;

      vis->indexBits      = 0;
      vis->depthBits      = depth_size;
      vis->stencilBits    = stencil_size;

      vis->accumRedBits   = accum_red_size;
      vis->accumGreenBits = accum_green_size;
      vis->accumBlueBits  = accum_blue_size;
      vis->accumAlphaBits = accum_alpha_size;

      vis->haveAccumBuffer   = accum_red_size > 0;
      vis->haveDepthBuffer   = depth_size > 0;
      vis->haveStencilBuffer = stencil_size > 0;

      vis->numAuxBuffers = 0;
      vis->level = 0;
      vis->sampleBuffers = 0;
      vis->samples = 0;
   }

   v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
   if (db_flag)
      v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
   if (stereo_flag) {
      v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
      if (db_flag)
         v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
   }

   v->stvis.color_format = choose_pixel_format(v);
   if (v->stvis.color_format == PIPE_FORMAT_NONE) {
      free(v->visinfo);
      free(v);
      return NULL;
   }

   v->stvis.depth_stencil_format =
      choose_depth_stencil_format(xmdpy, depth_size, stencil_size);

   v->stvis.accum_format = (accum_red_size +
         accum_green_size + accum_blue_size + accum_alpha_size) ?
      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;

   v->stvis.samples = num_samples;
   v->stvis.render_buffer = ST_ATTACHMENT_INVALID;

   /* XXX minor hack */
   v->mesa_visual.level = level;
   return v;
}
Пример #4
0
PUBLIC void
XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
                  const int *attrib_list)
{
   struct st_context_iface *st = stapi->get_current(stapi);
   struct st_framebuffer_iface* stfbi = drawable->stfb;
   struct pipe_resource *res;
   int x, y, w, h;
   enum st_attachment_type st_attachment = xmesa_attachment_type(buffer);

   x = 0;
   y = 0;
   w = drawable->width;
   h = drawable->height;

   /* We need to validate our attachments before using them,
    * in case the texture doesn't exist yet. */
   xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment);
   res = xmesa_get_attachment(stfbi, st_attachment);

   if (res) {
      struct pipe_context* pipe = xmesa_get_context(stfbi);
      enum pipe_format internal_format = res->format;
      struct pipe_transfer *tex_xfer;
      char *map;
      int line, ximage_stride;
      XImage *img;

      internal_format = choose_pixel_format(drawable->xm_visual);

      tex_xfer = pipe_get_transfer(pipe, res,
                                   0, 0,    /* level, layer */
                                   PIPE_TRANSFER_WRITE,
                                   x, y,
                                   w, h);
      if (!tex_xfer)
         return;

      /* Grab the XImage that we want to turn into a texture. */
      img = XGetImage(dpy,
                      drawable->ws.drawable,
                      x, y,
                      w, h,
                      AllPlanes,
                      ZPixmap);

      if (!img) {
         pipe_transfer_destroy(pipe, tex_xfer);
         return;
      }

      map = pipe_transfer_map(pipe, tex_xfer);

      if (!map) {
         pipe_transfer_destroy(pipe, tex_xfer);
         return;
      }

      /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
         We assume 32 bit pixels. */
      ximage_stride = w * 4;

      for (line = 0; line < h; line++)
         memcpy(&map[line * tex_xfer->stride],
                &img->data[line * ximage_stride],
                ximage_stride);

      pipe_transfer_unmap(pipe, tex_xfer);

      pipe_transfer_destroy(pipe, tex_xfer);

      st->teximage(st,
                   ST_TEXTURE_2D,
                   0,    /* level */
                   internal_format,
                   res,
                   FALSE /* no mipmap */);

   }
}
Пример #5
0
bool process(convert_params& params, convert_stats& stats) {
  texture_type tex_type = params.m_texture_type;

  crn_comp_params comp_params(params.m_comp_params);
  crn_mipmap_params mipmap_params(params.m_mipmap_params);

  progress_params progress_state;
  progress_state.m_pParams = &params;
  progress_state.m_canceled = false;
  progress_state.m_start_percentage = 0;

  params.m_status = false;
  params.m_error_message.clear();

  if (params.m_pIntermediate_texture) {
    crnlib_delete(params.m_pIntermediate_texture);
    params.m_pIntermediate_texture = NULL;
  }

  params.m_pIntermediate_texture = crnlib_new<mipmapped_texture>(*params.m_pInput_texture);

  mipmapped_texture& work_tex = *params.m_pInput_texture;

  if ((params.m_unflip) && (work_tex.is_flipped())) {
    console::info("Unflipping texture");
    work_tex.unflip(true, true);
  }

  if (params.m_y_flip) {
    console::info("Flipping texture on Y axis");

    // This is awkward - if we're writing to KTX, then go ahead and properly update the work texture's orientation flags.
    // Otherwise, don't bother updating the orientation flags because the writer may then attempt to unflip the texture before writing to formats
    // that don't support flipped textures (ugh).
    const bool bOutputFormatSupportsFlippedTextures = params.m_dst_file_type == texture_file_types::cFormatKTX;
    if (!work_tex.flip_y(bOutputFormatSupportsFlippedTextures)) {
      console::warning("Failed flipping texture on Y axis");
    }
  }

  if ((params.m_dst_format != PIXEL_FMT_INVALID) && (pixel_format_helpers::is_alpha_only(params.m_dst_format))) {
    if ((work_tex.get_comp_flags() & pixel_format_helpers::cCompFlagAValid) == 0) {
      console::warning("Output format is alpha-only, but input doesn't have alpha, so setting alpha to luminance.");

      work_tex.convert(PIXEL_FMT_A8, crnlib::dxt_image::pack_params());

      if (tex_type == cTextureTypeNormalMap)
        tex_type = cTextureTypeRegularMap;
    }
  }

  pixel_format dst_format = params.m_dst_format;
  if (pixel_format_helpers::is_dxt(dst_format)) {
    if ((params.m_dst_file_type != texture_file_types::cFormatCRN) &&
        (params.m_dst_file_type != texture_file_types::cFormatDDS) &&
        (params.m_dst_file_type != texture_file_types::cFormatKTX)) {
      console::warning("Output file format does not support DXTc - automatically choosing a non-DXT pixel format.");
      dst_format = PIXEL_FMT_INVALID;
    }
  }

  if (dst_format == PIXEL_FMT_INVALID) {
    // Caller didn't specify a format to use, so try to pick something reasonable.
    // This is actually much trickier than it seems, and the current approach kind of sucks.
    dst_format = choose_pixel_format(params, comp_params, work_tex, tex_type);
  }

  if ((dst_format == PIXEL_FMT_DXT1) && (comp_params.get_flag(cCRNCompFlagDXT1AForTransparency)))
    dst_format = PIXEL_FMT_DXT1A;
  else if (dst_format == PIXEL_FMT_DXT1A)
    comp_params.set_flag(cCRNCompFlagDXT1AForTransparency, true);

  if ((dst_format == PIXEL_FMT_DXT1A) && (params.m_dst_file_type == texture_file_types::cFormatCRN)) {
    console::warning("CRN file format does not support DXT1A compressed textures - converting to DXT5 instead.");
    dst_format = PIXEL_FMT_DXT5;
  }

  const bool is_normal_map = (tex_type == cTextureTypeNormalMap);
  bool perceptual = comp_params.get_flag(cCRNCompFlagPerceptual);
  if (is_normal_map) {
    perceptual = false;
    mipmap_params.m_gamma_filtering = false;
  }

  if (pixel_format_helpers::is_pixel_format_non_srgb(dst_format)) {
    if (perceptual) {
      console::message("Output pixel format is swizzled or not RGB, disabling perceptual color metrics");
      perceptual = false;
    }
  }

  if (pixel_format_helpers::is_normal_map(dst_format)) {
    if (perceptual)
      console::message("Output pixel format is intended for normal maps, disabling perceptual color metrics");

    perceptual = false;
  }

  bool generate_mipmaps = texture_file_types::supports_mipmaps(params.m_dst_file_type);
  if ((params.m_write_mipmaps_to_multiple_files) &&
      ((params.m_dst_file_type != texture_file_types::cFormatCRN) && (params.m_dst_file_type != texture_file_types::cFormatDDS) && (params.m_dst_file_type != texture_file_types::cFormatKTX))) {
    generate_mipmaps = true;
  }

  if (params.m_param_debugging) {
    params.print();

    print_comp_params(comp_params);
    print_mipmap_params(mipmap_params);
  }

  if (!create_texture_mipmaps(work_tex, comp_params, mipmap_params, generate_mipmaps))
    return convert_error(params, "Failed creating texture mipmaps!");

  bool formats_differ = work_tex.get_format() != dst_format;
  if (formats_differ) {
    if (pixel_format_helpers::is_dxt1(work_tex.get_format()) && pixel_format_helpers::is_dxt1(dst_format))
      formats_differ = false;
  }

  bool status = false;

  timer t;
  t.start();

  if ((params.m_dst_file_type == texture_file_types::cFormatCRN) ||
      ((params.m_dst_file_type == texture_file_types::cFormatDDS) && (pixel_format_helpers::is_dxt(dst_format)) &&
       //((formats_differ) || (comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel))
       ((comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel)))) {
    status = write_compressed_texture(work_tex, params, comp_params, dst_format, progress_state, perceptual, stats);
  } else {
    if ((comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel)) {
      console::warning("Target bitrate/quality level is not supported for this output file format.\n");
    }
    status = convert_and_write_normal_texture(work_tex, params, comp_params, dst_format, progress_state, formats_differ, perceptual, stats);
  }

  console::progress("");

  if (progress_state.m_canceled) {
    params.m_canceled = true;
    return false;
  }

  double total_write_time = t.get_elapsed_secs();

  if (status) {
    if (params.m_param_debugging)
      console::info("Work texture format: %s, desired destination format: %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format));

    console::message("Texture successfully written in %3.3fs", total_write_time);
  } else {
    dynamic_string str;

    if (work_tex.get_last_error().is_empty())
      str.format("Failed writing texture to file \"%s\"", params.m_dst_filename.get_ptr());
    else
      str.format("Failed writing texture to file \"%s\", Reason: %s", params.m_dst_filename.get_ptr(), work_tex.get_last_error().get_ptr());

    return convert_error(params, str.get_ptr());
  }

  if (params.m_debugging) {
    crnlib_print_mem_stats();
  }

  params.m_status = true;
  return true;
}
      bool process(convert_params& params, convert_stats& stats)
      {
         texture_type tex_type = params.m_texture_type;

         crn_comp_params comp_params(params.m_comp_params);
         crn_mipmap_params mipmap_params(params.m_mipmap_params);

         progress_params progress_state;
         progress_state.m_pParams = &params;
         progress_state.m_canceled = false;
         progress_state.m_start_percentage = 0;

         params.m_status = false;
         params.m_error_message.clear();

         if (params.m_pIntermediate_texture)
         {
            crnlib_delete(params.m_pIntermediate_texture);
            params.m_pIntermediate_texture = NULL;
         }

         params.m_pIntermediate_texture = crnlib_new<dds_texture>(*params.m_pInput_texture);

         dds_texture& work_tex = *params.m_pInput_texture;

         if ((params.m_dst_format != PIXEL_FMT_INVALID) && (pixel_format_helpers::is_alpha_only(params.m_dst_format)))
         {
            if ((work_tex.get_comp_flags() & pixel_format_helpers::cCompFlagAValid) == 0)
            {
               console::warning(L"Output format is alpha-only, but input doesn't have alpha, so setting alpha to luminance.");

               work_tex.convert(PIXEL_FMT_A8, crnlib::dxt_image::pack_params());

               if (tex_type == cTextureTypeNormalMap)
                  tex_type = cTextureTypeRegularMap;
            }
         }

         pixel_format dst_format = params.m_dst_format;

         if (dst_format == PIXEL_FMT_INVALID)
         {
            // Caller didn't specify a format to use, so try to pick something reasonable.
            // This is actually much trickier than it seems, and the current approach kind of sucks.
            dst_format = choose_pixel_format(params, comp_params, work_tex, tex_type);
         }

         if ((dst_format == PIXEL_FMT_DXT1) && (comp_params.get_flag(cCRNCompFlagDXT1AForTransparency)))
            dst_format = PIXEL_FMT_DXT1A;
         else if (dst_format == PIXEL_FMT_DXT1A)
            comp_params.set_flag(cCRNCompFlagDXT1AForTransparency, true);

         const bool is_normal_map = (tex_type == cTextureTypeNormalMap);
         bool perceptual = comp_params.get_flag(cCRNCompFlagPerceptual);
         if (is_normal_map)
         {
            perceptual = false;
            mipmap_params.m_gamma_filtering = false;
         }

         if (pixel_format_helpers::is_pixel_format_non_srgb(dst_format))
         {
            if (perceptual)
            {
               //console::warning(L"Output pixel format is swizzled or not RGB, disabling perceptual color metrics");
               perceptual = false;
            }
         }

         if (pixel_format_helpers::is_normal_map(dst_format))
         {
            //if (perceptual)
               //console::warning(L"Output pixel format is intended for normal maps, disabling perceptual color metrics");

            perceptual = false;
         }

         bool generate_mipmaps = texture_file_types::supports_mipmaps(params.m_dst_file_type);
         if ((params.m_write_mipmaps_to_multiple_files) && ((params.m_dst_file_type != texture_file_types::cFormatCRN) && (params.m_dst_file_type != texture_file_types::cFormatDDS)))
         {
            generate_mipmaps = true;
         }

         if (params.m_param_debugging)
         {
            params.print();

            print_comp_params(comp_params);
            print_mipmap_params(mipmap_params);
         }

         if (!create_texture_mipmaps(work_tex, comp_params, mipmap_params, generate_mipmaps))
            return convert_error(params, L"Failed creating texture mipmaps!");

         bool formats_differ = work_tex.get_format() != dst_format;
         if (formats_differ)
         {
            if (pixel_format_helpers::is_dxt1(work_tex.get_format()) && pixel_format_helpers::is_dxt1(dst_format))
               formats_differ = false;
         }

         bool status = false;

         timer t;
         t.start();

         if ( (params.m_dst_file_type == texture_file_types::cFormatCRN) ||
               ( (params.m_dst_file_type == texture_file_types::cFormatDDS) && (pixel_format_helpers::is_dxt(dst_format)) &&
                 ((formats_differ) || (comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel))
               )
            )
         {
            status = write_compressed_texture(work_tex, params, comp_params, dst_format, progress_state, perceptual, stats);
         }
         else
         {
            status = convert_and_write_normal_texture(work_tex, params, comp_params, dst_format, progress_state, formats_differ, perceptual, stats);
         }

         console::progress(L"");

         if (progress_state.m_canceled)
         {
            params.m_canceled = true;
            return false;
         }

         double total_write_time = t.get_elapsed_secs();

         if (status)
         {
            if (params.m_param_debugging)
               console::info(L"Work texture format: %s, desired destination format: %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format));

            console::message(L"Texture successfully written in %3.3fs", total_write_time);
         }
         else
         {
            dynamic_wstring str;

            if (work_tex.get_last_error().is_empty())
               str.format(L"Failed writing texture to file \"%s\"", params.m_dst_filename.get_ptr());
            else
               str.format(L"Failed writing texture to file \"%s\", Reason: %s", params.m_dst_filename.get_ptr(), work_tex.get_last_error().get_ptr());

            return convert_error(params, str.get_ptr());
         }

         if (params.m_debugging)
         {
            crnlib_print_mem_stats();
         }

         params.m_status = true;
         return true;
      }
GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
{
#ifdef GHOST_OPENGL_ALPHA
	const bool needAlpha = true;
#else
	const bool needAlpha = false;
#endif

#ifdef GHOST_OPENGL_STENCIL
	const bool needStencil = true;
#else
	const bool needStencil = false;
#endif

#ifdef GHOST_OPENGL_SRGB
	const bool sRGB = true;
#else
	const bool sRGB = false;
#endif

	HGLRC prevHGLRC;
	HDC   prevHDC;

	int iPixelFormat;
	int lastPFD;

	PIXELFORMATDESCRIPTOR chosenPFD;


	SetLastError(NO_ERROR);

	prevHGLRC = ::wglGetCurrentContext();
	WIN32_CHK(GetLastError() == NO_ERROR);

	prevHDC   = ::wglGetCurrentDC();
	WIN32_CHK(GetLastError() == NO_ERROR);

	iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);

	if (iPixelFormat == 0)
		goto error;

	lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);

	if (!WIN32_CHK(lastPFD != 0))
		goto error;

	if (needAlpha && chosenPFD.cAlphaBits == 0)
		fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");

	if (needStencil && chosenPFD.cStencilBits == 0)
		fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n");

	if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD)))
		goto error;

	activateWGLEW();

	if (WGLEW_ARB_create_context) {
		int profileBitCore   = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
		int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;

#ifdef WITH_GLEW_ES
		int profileBitES     = m_contextProfileMask & WGL_CONTEXT_ES_PROFILE_BIT_EXT;
#endif

		if (!WGLEW_ARB_create_context_profile && profileBitCore)
			fprintf(stderr, "Warning! OpenGL core profile not available.\n");

		if (!WGLEW_ARB_create_context_profile && profileBitCompat)
			fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");

#ifdef WITH_GLEW_ES
		if (!WGLEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
			fprintf(stderr, "Warning! OpenGL ES profile not available.\n");

		if (!WGLEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
			fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
#endif

		int profileMask = 0;

		if (WGLEW_ARB_create_context_profile && profileBitCore)
			profileMask |= profileBitCore;

		if (WGLEW_ARB_create_context_profile && profileBitCompat)
			profileMask |= profileBitCompat;

#ifdef WITH_GLEW_ES
		if (WGLEW_EXT_create_context_es_profile && profileBitES)
			profileMask |= profileBitES;
#endif

		if (profileMask != m_contextProfileMask)
			fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");

		std::vector<int> iAttributes;

		if (profileMask) {
			iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
			iAttributes.push_back(profileMask);
		}

		if (m_contextMajorVersion != 0) {
			iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
			iAttributes.push_back(m_contextMajorVersion);
		}

		if (m_contextMinorVersion != 0) {
			iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
			iAttributes.push_back(m_contextMinorVersion);
		}

		if (m_contextFlags != 0) {
			iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
			iAttributes.push_back(m_contextFlags);
		}

		if (m_contextResetNotificationStrategy != 0) {
			if (WGLEW_ARB_create_context_robustness) {
				iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
				iAttributes.push_back(m_contextResetNotificationStrategy);
			}
			else {
				fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
			}
		}

		iAttributes.push_back(0);

		if (!s_singleContextMode || s_sharedHGLRC == NULL)
			m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
		else
			m_hGLRC = s_sharedHGLRC;
	}
	else {
		if (m_contextProfileMask  != 0)
			fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL profiles.");

		if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0)
			fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL versions.");

		if (m_contextFlags != 0)
			fprintf(stderr, "Warning! Legacy WGL is unable to set context flags.");

		if (!s_singleContextMode || s_sharedHGLRC == NULL)
			m_hGLRC = ::wglCreateContext(m_hDC);
		else
			m_hGLRC = s_sharedHGLRC;
	}

	if (!WIN32_CHK(m_hGLRC != NULL))
		goto error;

	if (s_sharedHGLRC == NULL)
		s_sharedHGLRC = m_hGLRC;

	s_sharedCount++;

	if (!s_singleContextMode && s_sharedHGLRC != m_hGLRC && !WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC)))
		goto error;

	if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC)))
		goto error;

	initContextGLEW();

	initClearGL();
	::SwapBuffers(m_hDC);

#ifndef NDEBUG
	reportContextString("Vendor",   m_dummyVendor,   reinterpret_cast<const char*>(glGetString(GL_VENDOR)));
	reportContextString("Renderer", m_dummyRenderer, reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
	reportContextString("Version",  m_dummyVersion,  reinterpret_cast<const char*>(glGetString(GL_VERSION)));
#endif

	return GHOST_kSuccess;

error:
	::wglMakeCurrent(prevHDC, prevHGLRC);

	return GHOST_kFailure;
}