/usr/src/castle-game-engine-5.2.0/opengl/castleglimages_savescreen.inc is in castle-game-engine-src 5.2.0-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | {
Copyright 2001-2014 Michalis Kamburelis.
This file is part of "Castle Game Engine".
"Castle Game Engine" is free software; see the file COPYING.txt,
included in this distribution, for details about the copyright.
"Castle Game Engine" is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------------------------------
}
{ Part of CastleGLImages unit: saving screen. }
{$ifdef read_interface}
type
TColorBuffer = (
cbFront,
cbBack,
cbColorAttachment0
);
{ Notes about saving images from cbFront buffer:
Don't do it. It just not defined what will be returned when you read from
the front buffer. When our OpenGL context is covered by some other window,
then glReadPixels *may* return pixels with contents of obscuring window.
It doesn't help to draw right before trying to save buffer contents,
reading from front buffer is just not reliable.
The only reliable way to save screen contents is to draw something to back
buffer and (without doing any swapbuffers) read it from cbBack buffer.
This is only possible if you have double-buffered window, of course.
}
{ Save the current color buffer contents to image.
The suffix "NoFlush" is there to remind you that this
function grabs the @italic(current) buffer contents. Usually you want to
redraw the screen to the back buffer, and call this function to capture
back buffer @italic(before) swapping, since this is the only reliable
way to capture OpenGL screen.
Just use TCastleWindowCustom.SaveScreen to do it automatically.
Version with ImageClass can save to any image format from PixelsImageClasses.
Version with TCastleImage instance just uses this instance to save the image.
You must pass here already created TCastleImage instance, it's class,
Width and Height will be used when saving.
@raises(EImageClassNotSupportedForOpenGL When Image class is not supported
by OpenGL.)
@groupBegin }
function SaveScreen_NoFlush(
const Rect: TRectangle; const ReadBuffer: TColorBuffer): TRGBImage; overload;
function SaveScreen_NoFlush(const ImageClass: TCastleImageClass;
const Rect: TRectangle; const ReadBuffer: TColorBuffer): TCastleImage; overload;
procedure SaveScreen_NoFlush(const Image: TCastleImage;
const Left, Bottom: Integer; const ReadBuffer: TColorBuffer); overload;
{ @groupEnd }
{ Captures current screen as a TGLImage instance, ready to be drawn on 2D screen. }
function SaveScreenToGL_NoFlush(const Rect: TRectangle;
const ReadBuffer: TColorBuffer;
const ScalingPossible: boolean = false): TGLImage;
{$endif read_interface}
{$ifdef read_implementation}
const
ColorBufferGL: array [TColorBuffer] of TGLenum = (
GL_FRONT,
GL_BACK,
GL_COLOR_ATTACHMENT0
);
{ This is the basis for all other SaveScreen* functions below. }
procedure SaveScreen_NoFlush(const Image: TCastleImage;
const Left, Bottom: Integer; const ReadBuffer: TColorBuffer);
procedure ReadPixels(const Image: TCastleImage);
var
PackData: TPackNotAlignedData;
begin
BeforePackImage(PackData, Image);
try
SetReadBuffer(ColorBufferGL[ReadBuffer]);
glReadPixels(Left, Bottom, Image.Width, Image.Height, ImageGLFormat(Image),
ImageGLType(Image), Image.RawPixels);
finally AfterPackImage(PackData, Image) end;
end;
{$ifdef OpenGLES}
{ Under OpenGLES, the only type+format combination that is guaranteed
to work is GL_RGBA + GL_UNSIGNED_BYTE,
see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glReadPixels.xml .
So grab image to TRGBAlphaImage, and later convert it as necessary. }
var
ImageRGBA: TRGBAlphaImage;
begin
if Image is TRGBAlphaImage then
ReadPixels(Image) else
begin
ImageRGBA := TRGBAlphaImage.Create(Image.Width, Image.Height, Image.Depth);
try
ReadPixels(ImageRGBA);
Image.Assign(ImageRGBA);
finally FreeAndNil(ImageRGBA) end;
end;
{$else}
begin
ReadPixels(Image);
{$endif}
end;
function SaveScreen_NoFlush(const ImageClass: TCastleImageClass;
const Rect: TRectangle; const ReadBuffer: TColorBuffer): TCastleImage;
begin
Result := ImageClass.Create(Rect.Width, Rect.Height);
try
SaveScreen_NoFlush(Result, Rect.Left, Rect.Bottom, ReadBuffer);
except Result.Free; raise end;
end;
function SaveScreen_NoFlush(const Rect: TRectangle;
const ReadBuffer: TColorBuffer): TRGBImage;
begin
Result := SaveScreen_NoFlush(TRGBImage, Rect, ReadBuffer) as TRGBImage;
end;
function SaveScreenToGL_NoFlush(const Rect: TRectangle;
const ReadBuffer: TColorBuffer;
const ScalingPossible: boolean): TGLImage;
var
ScreenImage: TRGBImage;
begin
ScreenImage := SaveScreen_NoFlush(Rect, ReadBuffer);
try
Result := TGLImage.Create(ScreenImage, ScalingPossible);
finally FreeAndNil(ScreenImage) end;
end;
{$endif read_implementation}
|