Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* GLScreenBuffer is the abstraction for the "default framebuffer" used |
michael@0 | 7 | * by an offscreen GLContext. Since it's only for offscreen GLContext's, |
michael@0 | 8 | * it's only useful for things like WebGL, and is NOT used by the |
michael@0 | 9 | * compositor's GLContext. Remember that GLContext provides an abstraction |
michael@0 | 10 | * so that even if you want to draw to the 'screen', even if that's not |
michael@0 | 11 | * actually the screen, just draw to 0. This GLScreenBuffer class takes the |
michael@0 | 12 | * logic handling out of GLContext. |
michael@0 | 13 | */ |
michael@0 | 14 | |
michael@0 | 15 | #ifndef SCREEN_BUFFER_H_ |
michael@0 | 16 | #define SCREEN_BUFFER_H_ |
michael@0 | 17 | |
michael@0 | 18 | #include "SurfaceTypes.h" |
michael@0 | 19 | #include "SurfaceStream.h" |
michael@0 | 20 | #include "GLContextTypes.h" |
michael@0 | 21 | #include "GLDefs.h" |
michael@0 | 22 | #include "mozilla/gfx/2D.h" |
michael@0 | 23 | #include "mozilla/gfx/Point.h" |
michael@0 | 24 | |
michael@0 | 25 | // Forwards: |
michael@0 | 26 | class gfxImageSurface; |
michael@0 | 27 | |
michael@0 | 28 | namespace mozilla { |
michael@0 | 29 | namespace gfx { |
michael@0 | 30 | class SurfaceStream; |
michael@0 | 31 | class SharedSurface; |
michael@0 | 32 | } |
michael@0 | 33 | namespace gl { |
michael@0 | 34 | class GLContext; |
michael@0 | 35 | class SharedSurface_GL; |
michael@0 | 36 | class SurfaceFactory_GL; |
michael@0 | 37 | } |
michael@0 | 38 | } |
michael@0 | 39 | |
michael@0 | 40 | namespace mozilla { |
michael@0 | 41 | namespace gl { |
michael@0 | 42 | |
michael@0 | 43 | class DrawBuffer |
michael@0 | 44 | { |
michael@0 | 45 | protected: |
michael@0 | 46 | typedef struct gfx::SurfaceCaps SurfaceCaps; |
michael@0 | 47 | |
michael@0 | 48 | public: |
michael@0 | 49 | // Infallible, may return null if unneeded. |
michael@0 | 50 | static DrawBuffer* Create(GLContext* const gl, |
michael@0 | 51 | const SurfaceCaps& caps, |
michael@0 | 52 | const GLFormats& formats, |
michael@0 | 53 | const gfx::IntSize& size); |
michael@0 | 54 | |
michael@0 | 55 | protected: |
michael@0 | 56 | GLContext* const mGL; |
michael@0 | 57 | const gfx::IntSize mSize; |
michael@0 | 58 | const GLuint mFB; |
michael@0 | 59 | const GLuint mColorMSRB; |
michael@0 | 60 | const GLuint mDepthRB; |
michael@0 | 61 | const GLuint mStencilRB; |
michael@0 | 62 | |
michael@0 | 63 | DrawBuffer(GLContext* gl, |
michael@0 | 64 | const gfx::IntSize& size, |
michael@0 | 65 | GLuint fb, |
michael@0 | 66 | GLuint colorMSRB, |
michael@0 | 67 | GLuint depthRB, |
michael@0 | 68 | GLuint stencilRB) |
michael@0 | 69 | : mGL(gl) |
michael@0 | 70 | , mSize(size) |
michael@0 | 71 | , mFB(fb) |
michael@0 | 72 | , mColorMSRB(colorMSRB) |
michael@0 | 73 | , mDepthRB(depthRB) |
michael@0 | 74 | , mStencilRB(stencilRB) |
michael@0 | 75 | {} |
michael@0 | 76 | |
michael@0 | 77 | public: |
michael@0 | 78 | virtual ~DrawBuffer(); |
michael@0 | 79 | |
michael@0 | 80 | const gfx::IntSize& Size() const { |
michael@0 | 81 | return mSize; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | GLuint FB() const { |
michael@0 | 85 | return mFB; |
michael@0 | 86 | } |
michael@0 | 87 | }; |
michael@0 | 88 | |
michael@0 | 89 | class ReadBuffer |
michael@0 | 90 | { |
michael@0 | 91 | protected: |
michael@0 | 92 | typedef struct gfx::SurfaceCaps SurfaceCaps; |
michael@0 | 93 | |
michael@0 | 94 | public: |
michael@0 | 95 | // Infallible, always non-null. |
michael@0 | 96 | static ReadBuffer* Create(GLContext* gl, |
michael@0 | 97 | const SurfaceCaps& caps, |
michael@0 | 98 | const GLFormats& formats, |
michael@0 | 99 | SharedSurface_GL* surf); |
michael@0 | 100 | |
michael@0 | 101 | protected: |
michael@0 | 102 | GLContext* const mGL; |
michael@0 | 103 | |
michael@0 | 104 | const GLuint mFB; |
michael@0 | 105 | // mFB has the following attachments: |
michael@0 | 106 | const GLuint mDepthRB; |
michael@0 | 107 | const GLuint mStencilRB; |
michael@0 | 108 | // note no mColorRB here: this is provided by mSurf. |
michael@0 | 109 | SharedSurface_GL* mSurf; // Owned by GLScreenBuffer's SurfaceStream. |
michael@0 | 110 | |
michael@0 | 111 | ReadBuffer(GLContext* gl, |
michael@0 | 112 | GLuint fb, |
michael@0 | 113 | GLuint depthRB, |
michael@0 | 114 | GLuint stencilRB, |
michael@0 | 115 | SharedSurface_GL* surf) |
michael@0 | 116 | : mGL(gl) |
michael@0 | 117 | , mFB(fb) |
michael@0 | 118 | , mDepthRB(depthRB) |
michael@0 | 119 | , mStencilRB(stencilRB) |
michael@0 | 120 | , mSurf(surf) |
michael@0 | 121 | {} |
michael@0 | 122 | |
michael@0 | 123 | public: |
michael@0 | 124 | virtual ~ReadBuffer(); |
michael@0 | 125 | |
michael@0 | 126 | // Cannot attach a surf of a different AttachType or Size than before. |
michael@0 | 127 | void Attach(SharedSurface_GL* surf); |
michael@0 | 128 | |
michael@0 | 129 | const gfx::IntSize& Size() const; |
michael@0 | 130 | |
michael@0 | 131 | GLuint FB() const { |
michael@0 | 132 | return mFB; |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | SharedSurface_GL* SharedSurf() const { |
michael@0 | 136 | return mSurf; |
michael@0 | 137 | } |
michael@0 | 138 | }; |
michael@0 | 139 | |
michael@0 | 140 | |
michael@0 | 141 | class GLScreenBuffer |
michael@0 | 142 | { |
michael@0 | 143 | protected: |
michael@0 | 144 | typedef class gfx::SurfaceStream SurfaceStream; |
michael@0 | 145 | typedef class gfx::SharedSurface SharedSurface; |
michael@0 | 146 | typedef gfx::SurfaceStreamType SurfaceStreamType; |
michael@0 | 147 | typedef gfx::SharedSurfaceType SharedSurfaceType; |
michael@0 | 148 | typedef struct gfx::SurfaceCaps SurfaceCaps; |
michael@0 | 149 | |
michael@0 | 150 | public: |
michael@0 | 151 | // Infallible. |
michael@0 | 152 | static GLScreenBuffer* Create(GLContext* gl, |
michael@0 | 153 | const gfx::IntSize& size, |
michael@0 | 154 | const SurfaceCaps& caps); |
michael@0 | 155 | |
michael@0 | 156 | protected: |
michael@0 | 157 | GLContext* const mGL; // Owns us. |
michael@0 | 158 | SurfaceCaps mCaps; |
michael@0 | 159 | SurfaceFactory_GL* mFactory; // Owned by us. |
michael@0 | 160 | RefPtr<SurfaceStream> mStream; |
michael@0 | 161 | |
michael@0 | 162 | DrawBuffer* mDraw; // Owned by us. |
michael@0 | 163 | ReadBuffer* mRead; // Owned by us. |
michael@0 | 164 | |
michael@0 | 165 | bool mNeedsBlit; |
michael@0 | 166 | |
michael@0 | 167 | // Below are the parts that help us pretend to be framebuffer 0: |
michael@0 | 168 | GLuint mUserDrawFB; |
michael@0 | 169 | GLuint mUserReadFB; |
michael@0 | 170 | GLuint mInternalDrawFB; |
michael@0 | 171 | GLuint mInternalReadFB; |
michael@0 | 172 | |
michael@0 | 173 | #ifdef DEBUG |
michael@0 | 174 | bool mInInternalMode_DrawFB; |
michael@0 | 175 | bool mInInternalMode_ReadFB; |
michael@0 | 176 | #endif |
michael@0 | 177 | |
michael@0 | 178 | GLScreenBuffer(GLContext* gl, |
michael@0 | 179 | const SurfaceCaps& caps, |
michael@0 | 180 | SurfaceFactory_GL* factory, |
michael@0 | 181 | SurfaceStream* stream) |
michael@0 | 182 | : mGL(gl) |
michael@0 | 183 | , mCaps(caps) |
michael@0 | 184 | , mFactory(factory) |
michael@0 | 185 | , mStream(stream) |
michael@0 | 186 | , mDraw(nullptr) |
michael@0 | 187 | , mRead(nullptr) |
michael@0 | 188 | , mNeedsBlit(true) |
michael@0 | 189 | , mUserDrawFB(0) |
michael@0 | 190 | , mUserReadFB(0) |
michael@0 | 191 | , mInternalDrawFB(0) |
michael@0 | 192 | , mInternalReadFB(0) |
michael@0 | 193 | #ifdef DEBUG |
michael@0 | 194 | , mInInternalMode_DrawFB(true) |
michael@0 | 195 | , mInInternalMode_ReadFB(true) |
michael@0 | 196 | #endif |
michael@0 | 197 | {} |
michael@0 | 198 | |
michael@0 | 199 | public: |
michael@0 | 200 | virtual ~GLScreenBuffer(); |
michael@0 | 201 | |
michael@0 | 202 | SurfaceStream* Stream() const { |
michael@0 | 203 | return mStream; |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | SurfaceFactory_GL* Factory() const { |
michael@0 | 207 | return mFactory; |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | SharedSurface_GL* SharedSurf() const { |
michael@0 | 211 | MOZ_ASSERT(mRead); |
michael@0 | 212 | return mRead->SharedSurf(); |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | bool PreserveBuffer() const { |
michael@0 | 216 | return mCaps.preserve; |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | const SurfaceCaps& Caps() const { |
michael@0 | 220 | return mCaps; |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | GLuint DrawFB() const { |
michael@0 | 224 | if (!mDraw) |
michael@0 | 225 | return ReadFB(); |
michael@0 | 226 | |
michael@0 | 227 | return mDraw->FB(); |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | GLuint ReadFB() const { |
michael@0 | 231 | return mRead->FB(); |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | void DeletingFB(GLuint fb); |
michael@0 | 235 | |
michael@0 | 236 | const gfx::IntSize& Size() const { |
michael@0 | 237 | MOZ_ASSERT(mRead); |
michael@0 | 238 | MOZ_ASSERT(!mDraw || mDraw->Size() == mRead->Size()); |
michael@0 | 239 | return mRead->Size(); |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | void BindAsFramebuffer(GLContext* const gl, GLenum target) const; |
michael@0 | 243 | |
michael@0 | 244 | void RequireBlit(); |
michael@0 | 245 | void AssureBlitted(); |
michael@0 | 246 | void AfterDrawCall(); |
michael@0 | 247 | void BeforeReadCall(); |
michael@0 | 248 | |
michael@0 | 249 | /** |
michael@0 | 250 | * Attempts to read pixels from the current bound framebuffer, if |
michael@0 | 251 | * it is backed by a SharedSurface_GL. |
michael@0 | 252 | * |
michael@0 | 253 | * Returns true if the pixel data has been read back, false |
michael@0 | 254 | * otherwise. |
michael@0 | 255 | */ |
michael@0 | 256 | bool ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, |
michael@0 | 257 | GLenum format, GLenum type, GLvoid *pixels); |
michael@0 | 258 | |
michael@0 | 259 | /* Morph swaps out our SurfaceStream mechanism and replaces it with |
michael@0 | 260 | * one best suited to our platform and compositor configuration. |
michael@0 | 261 | * |
michael@0 | 262 | * Must be called on the producing thread. |
michael@0 | 263 | * We haven't made any guarantee that rendering is actually |
michael@0 | 264 | * done when Morph is run, just that it can't run concurrently |
michael@0 | 265 | * with rendering. This means that we can't just drop the contents |
michael@0 | 266 | * of the buffer, since we may only be partially done rendering. |
michael@0 | 267 | * |
michael@0 | 268 | * Once you pass newFactory into Morph, newFactory will be owned by |
michael@0 | 269 | * GLScreenBuffer, so `forget` any references to it that still exist. |
michael@0 | 270 | */ |
michael@0 | 271 | void Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamType); |
michael@0 | 272 | |
michael@0 | 273 | protected: |
michael@0 | 274 | // Returns false on error or inability to resize. |
michael@0 | 275 | bool Swap(const gfx::IntSize& size); |
michael@0 | 276 | |
michael@0 | 277 | public: |
michael@0 | 278 | bool PublishFrame(const gfx::IntSize& size); |
michael@0 | 279 | |
michael@0 | 280 | bool Resize(const gfx::IntSize& size); |
michael@0 | 281 | |
michael@0 | 282 | void Readback(SharedSurface_GL* src, gfx::DataSourceSurface* dest); |
michael@0 | 283 | void DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest); |
michael@0 | 284 | |
michael@0 | 285 | protected: |
michael@0 | 286 | void Attach(SharedSurface* surface, const gfx::IntSize& size); |
michael@0 | 287 | |
michael@0 | 288 | DrawBuffer* CreateDraw(const gfx::IntSize& size); |
michael@0 | 289 | ReadBuffer* CreateRead(SharedSurface_GL* surf); |
michael@0 | 290 | |
michael@0 | 291 | public: |
michael@0 | 292 | /* `fb` in these functions is the framebuffer the GLContext is hoping to |
michael@0 | 293 | * bind. When this is 0, we intercept the call and bind our own |
michael@0 | 294 | * framebuffers. As a client of these functions, just bind 0 when you want |
michael@0 | 295 | * to draw to the default framebuffer/'screen'. |
michael@0 | 296 | */ |
michael@0 | 297 | void BindFB(GLuint fb); |
michael@0 | 298 | void BindDrawFB(GLuint fb); |
michael@0 | 299 | void BindReadFB(GLuint fb); |
michael@0 | 300 | GLuint GetFB() const; |
michael@0 | 301 | GLuint GetDrawFB() const; |
michael@0 | 302 | GLuint GetReadFB() const; |
michael@0 | 303 | |
michael@0 | 304 | // Here `fb` is the actual framebuffer you want bound. Binding 0 will |
michael@0 | 305 | // bind the (generally useless) default framebuffer. |
michael@0 | 306 | void BindDrawFB_Internal(GLuint fb); |
michael@0 | 307 | void BindReadFB_Internal(GLuint fb); |
michael@0 | 308 | }; |
michael@0 | 309 | |
michael@0 | 310 | } // namespace gl |
michael@0 | 311 | } // namespace mozilla |
michael@0 | 312 | |
michael@0 | 313 | #endif // SCREEN_BUFFER_H_ |