Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
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 | #include "TextureImageEGL.h" |
michael@0 | 7 | #include "GLLibraryEGL.h" |
michael@0 | 8 | #include "GLContext.h" |
michael@0 | 9 | #include "GLUploadHelpers.h" |
michael@0 | 10 | #include "gfxPlatform.h" |
michael@0 | 11 | #include "gfx2DGlue.h" |
michael@0 | 12 | #include "mozilla/gfx/Types.h" |
michael@0 | 13 | |
michael@0 | 14 | namespace mozilla { |
michael@0 | 15 | namespace gl { |
michael@0 | 16 | |
michael@0 | 17 | static GLenum |
michael@0 | 18 | GLFormatForImage(gfx::SurfaceFormat aFormat) |
michael@0 | 19 | { |
michael@0 | 20 | switch (aFormat) { |
michael@0 | 21 | case gfx::SurfaceFormat::B8G8R8A8: |
michael@0 | 22 | case gfx::SurfaceFormat::B8G8R8X8: |
michael@0 | 23 | return LOCAL_GL_RGBA; |
michael@0 | 24 | case gfx::SurfaceFormat::R5G6B5: |
michael@0 | 25 | return LOCAL_GL_RGB; |
michael@0 | 26 | case gfx::SurfaceFormat::A8: |
michael@0 | 27 | return LOCAL_GL_LUMINANCE; |
michael@0 | 28 | default: |
michael@0 | 29 | NS_WARNING("Unknown GL format for Surface format"); |
michael@0 | 30 | } |
michael@0 | 31 | return 0; |
michael@0 | 32 | } |
michael@0 | 33 | |
michael@0 | 34 | static GLenum |
michael@0 | 35 | GLTypeForImage(gfx::SurfaceFormat aFormat) |
michael@0 | 36 | { |
michael@0 | 37 | switch (aFormat) { |
michael@0 | 38 | case gfx::SurfaceFormat::B8G8R8A8: |
michael@0 | 39 | case gfx::SurfaceFormat::B8G8R8X8: |
michael@0 | 40 | case gfx::SurfaceFormat::A8: |
michael@0 | 41 | return LOCAL_GL_UNSIGNED_BYTE; |
michael@0 | 42 | case gfx::SurfaceFormat::R5G6B5: |
michael@0 | 43 | return LOCAL_GL_UNSIGNED_SHORT_5_6_5; |
michael@0 | 44 | default: |
michael@0 | 45 | NS_WARNING("Unknown GL format for Surface format"); |
michael@0 | 46 | } |
michael@0 | 47 | return 0; |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | TextureImageEGL::TextureImageEGL(GLuint aTexture, |
michael@0 | 51 | const nsIntSize& aSize, |
michael@0 | 52 | GLenum aWrapMode, |
michael@0 | 53 | ContentType aContentType, |
michael@0 | 54 | GLContext* aContext, |
michael@0 | 55 | Flags aFlags, |
michael@0 | 56 | TextureState aTextureState, |
michael@0 | 57 | TextureImage::ImageFormat aImageFormat) |
michael@0 | 58 | : TextureImage(aSize, aWrapMode, aContentType, aFlags) |
michael@0 | 59 | , mGLContext(aContext) |
michael@0 | 60 | , mUpdateFormat(gfx::ImageFormatToSurfaceFormat(aImageFormat)) |
michael@0 | 61 | , mEGLImage(nullptr) |
michael@0 | 62 | , mTexture(aTexture) |
michael@0 | 63 | , mSurface(nullptr) |
michael@0 | 64 | , mConfig(nullptr) |
michael@0 | 65 | , mTextureState(aTextureState) |
michael@0 | 66 | , mBound(false) |
michael@0 | 67 | { |
michael@0 | 68 | if (mUpdateFormat == gfx::SurfaceFormat::UNKNOWN) { |
michael@0 | 69 | mUpdateFormat = gfx::ImageFormatToSurfaceFormat( |
michael@0 | 70 | gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType())); |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | if (mUpdateFormat == gfx::SurfaceFormat::R5G6B5) { |
michael@0 | 74 | mTextureFormat = gfx::SurfaceFormat::R8G8B8X8; |
michael@0 | 75 | } else if (mUpdateFormat == gfx::SurfaceFormat::B8G8R8X8) { |
michael@0 | 76 | mTextureFormat = gfx::SurfaceFormat::B8G8R8X8; |
michael@0 | 77 | } else { |
michael@0 | 78 | mTextureFormat = gfx::SurfaceFormat::B8G8R8A8; |
michael@0 | 79 | } |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | TextureImageEGL::~TextureImageEGL() |
michael@0 | 83 | { |
michael@0 | 84 | if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) { |
michael@0 | 85 | return; |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | // If we have a context, then we need to delete the texture; |
michael@0 | 89 | // if we don't have a context (either real or shared), |
michael@0 | 90 | // then they went away when the contex was deleted, because it |
michael@0 | 91 | // was the only one that had access to it. |
michael@0 | 92 | mGLContext->MakeCurrent(); |
michael@0 | 93 | mGLContext->fDeleteTextures(1, &mTexture); |
michael@0 | 94 | ReleaseTexImage(); |
michael@0 | 95 | DestroyEGLSurface(); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | void |
michael@0 | 99 | TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion) |
michael@0 | 100 | { |
michael@0 | 101 | if (mTextureState != Valid) { |
michael@0 | 102 | // if the texture hasn't been initialized yet, force the |
michael@0 | 103 | // client to paint everything |
michael@0 | 104 | aForRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize)); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | // We can only draw a rectangle, not subregions due to |
michael@0 | 108 | // the way that our texture upload functions work. If |
michael@0 | 109 | // needed, we /could/ do multiple texture uploads if we have |
michael@0 | 110 | // non-overlapping rects, but that's a tradeoff. |
michael@0 | 111 | aForRegion = nsIntRegion(aForRegion.GetBounds()); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | gfx::DrawTarget* |
michael@0 | 115 | TextureImageEGL::BeginUpdate(nsIntRegion& aRegion) |
michael@0 | 116 | { |
michael@0 | 117 | NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?"); |
michael@0 | 118 | |
michael@0 | 119 | // determine the region the client will need to repaint |
michael@0 | 120 | GetUpdateRegion(aRegion); |
michael@0 | 121 | mUpdateRect = aRegion.GetBounds(); |
michael@0 | 122 | |
michael@0 | 123 | //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height); |
michael@0 | 124 | if (!nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize)).Contains(mUpdateRect)) { |
michael@0 | 125 | NS_ERROR("update outside of image"); |
michael@0 | 126 | return nullptr; |
michael@0 | 127 | } |
michael@0 | 128 | |
michael@0 | 129 | //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat); |
michael@0 | 130 | |
michael@0 | 131 | mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO, |
michael@0 | 132 | gfx::IntSize(mUpdateRect.width, mUpdateRect.height), |
michael@0 | 133 | mUpdateFormat); |
michael@0 | 134 | |
michael@0 | 135 | return mUpdateDrawTarget; |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | void |
michael@0 | 139 | TextureImageEGL::EndUpdate() |
michael@0 | 140 | { |
michael@0 | 141 | NS_ASSERTION(!!mUpdateDrawTarget, "EndUpdate() without BeginUpdate()?"); |
michael@0 | 142 | |
michael@0 | 143 | //printf_stderr("EndUpdate: slow path"); |
michael@0 | 144 | |
michael@0 | 145 | // This is the slower path -- we didn't have any way to set up |
michael@0 | 146 | // a fast mapping between our cairo target surface and the GL |
michael@0 | 147 | // texture, so we have to upload data. |
michael@0 | 148 | |
michael@0 | 149 | RefPtr<gfx::SourceSurface> updateSurface = nullptr; |
michael@0 | 150 | RefPtr<gfx::DataSourceSurface> uploadImage = nullptr; |
michael@0 | 151 | gfx::IntSize updateSize(mUpdateRect.width, mUpdateRect.height); |
michael@0 | 152 | |
michael@0 | 153 | NS_ASSERTION(mUpdateDrawTarget->GetSize() == updateSize, |
michael@0 | 154 | "Upload image is the wrong size!"); |
michael@0 | 155 | |
michael@0 | 156 | updateSurface = mUpdateDrawTarget->Snapshot(); |
michael@0 | 157 | uploadImage = updateSurface->GetDataSurface(); |
michael@0 | 158 | |
michael@0 | 159 | if (!uploadImage) { |
michael@0 | 160 | return; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | mGLContext->MakeCurrent(); |
michael@0 | 164 | mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); |
michael@0 | 165 | |
michael@0 | 166 | if (mTextureState != Valid) { |
michael@0 | 167 | NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 && |
michael@0 | 168 | mUpdateRect.Size() == gfx::ThebesIntSize(mSize), |
michael@0 | 169 | "Bad initial update on non-created texture!"); |
michael@0 | 170 | |
michael@0 | 171 | mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, |
michael@0 | 172 | 0, |
michael@0 | 173 | GLFormatForImage(mUpdateFormat), |
michael@0 | 174 | mUpdateRect.width, |
michael@0 | 175 | mUpdateRect.height, |
michael@0 | 176 | 0, |
michael@0 | 177 | GLFormatForImage(uploadImage->GetFormat()), |
michael@0 | 178 | GLTypeForImage(uploadImage->GetFormat()), |
michael@0 | 179 | uploadImage->GetData()); |
michael@0 | 180 | } else { |
michael@0 | 181 | mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, |
michael@0 | 182 | 0, |
michael@0 | 183 | mUpdateRect.x, |
michael@0 | 184 | mUpdateRect.y, |
michael@0 | 185 | mUpdateRect.width, |
michael@0 | 186 | mUpdateRect.height, |
michael@0 | 187 | GLFormatForImage(uploadImage->GetFormat()), |
michael@0 | 188 | GLTypeForImage(uploadImage->GetFormat()), |
michael@0 | 189 | uploadImage->GetData()); |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | mUpdateDrawTarget = nullptr; |
michael@0 | 193 | mTextureState = Valid; |
michael@0 | 194 | return; // mTexture is bound |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | bool |
michael@0 | 198 | TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom /* = gfx::IntPoint(0,0) */) |
michael@0 | 199 | { |
michael@0 | 200 | nsIntRect bounds = aRegion.GetBounds(); |
michael@0 | 201 | |
michael@0 | 202 | nsIntRegion region; |
michael@0 | 203 | if (mTextureState != Valid) { |
michael@0 | 204 | bounds = nsIntRect(0, 0, mSize.width, mSize.height); |
michael@0 | 205 | region = nsIntRegion(bounds); |
michael@0 | 206 | } else { |
michael@0 | 207 | region = aRegion; |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | mTextureFormat = |
michael@0 | 211 | UploadSurfaceToTexture(mGLContext, |
michael@0 | 212 | aSurf, |
michael@0 | 213 | region, |
michael@0 | 214 | mTexture, |
michael@0 | 215 | mTextureState == Created, |
michael@0 | 216 | bounds.TopLeft() + nsIntPoint(aFrom.x, aFrom.y), |
michael@0 | 217 | false); |
michael@0 | 218 | |
michael@0 | 219 | mTextureState = Valid; |
michael@0 | 220 | return true; |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | void |
michael@0 | 224 | TextureImageEGL::BindTexture(GLenum aTextureUnit) |
michael@0 | 225 | { |
michael@0 | 226 | // Ensure the texture is allocated before it is used. |
michael@0 | 227 | if (mTextureState == Created) { |
michael@0 | 228 | Resize(mSize); |
michael@0 | 229 | } |
michael@0 | 230 | |
michael@0 | 231 | mGLContext->fActiveTexture(aTextureUnit); |
michael@0 | 232 | mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); |
michael@0 | 233 | mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); |
michael@0 | 234 | } |
michael@0 | 235 | |
michael@0 | 236 | void |
michael@0 | 237 | TextureImageEGL::Resize(const gfx::IntSize& aSize) |
michael@0 | 238 | { |
michael@0 | 239 | NS_ASSERTION(!mUpdateDrawTarget, "Resize() while in update?"); |
michael@0 | 240 | |
michael@0 | 241 | if (mSize == aSize && mTextureState != Created) |
michael@0 | 242 | return; |
michael@0 | 243 | |
michael@0 | 244 | mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); |
michael@0 | 245 | |
michael@0 | 246 | mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, |
michael@0 | 247 | 0, |
michael@0 | 248 | GLFormatForImage(mUpdateFormat), |
michael@0 | 249 | aSize.width, |
michael@0 | 250 | aSize.height, |
michael@0 | 251 | 0, |
michael@0 | 252 | GLFormatForImage(mUpdateFormat), |
michael@0 | 253 | GLTypeForImage(mUpdateFormat), |
michael@0 | 254 | nullptr); |
michael@0 | 255 | |
michael@0 | 256 | mTextureState = Allocated; |
michael@0 | 257 | mSize = aSize; |
michael@0 | 258 | } |
michael@0 | 259 | |
michael@0 | 260 | bool |
michael@0 | 261 | TextureImageEGL::BindTexImage() |
michael@0 | 262 | { |
michael@0 | 263 | if (mBound && !ReleaseTexImage()) |
michael@0 | 264 | return false; |
michael@0 | 265 | |
michael@0 | 266 | EGLBoolean success = |
michael@0 | 267 | sEGLLibrary.fBindTexImage(EGL_DISPLAY(), |
michael@0 | 268 | (EGLSurface)mSurface, |
michael@0 | 269 | LOCAL_EGL_BACK_BUFFER); |
michael@0 | 270 | |
michael@0 | 271 | if (success == LOCAL_EGL_FALSE) |
michael@0 | 272 | return false; |
michael@0 | 273 | |
michael@0 | 274 | mBound = true; |
michael@0 | 275 | return true; |
michael@0 | 276 | } |
michael@0 | 277 | |
michael@0 | 278 | bool |
michael@0 | 279 | TextureImageEGL::ReleaseTexImage() |
michael@0 | 280 | { |
michael@0 | 281 | if (!mBound) |
michael@0 | 282 | return true; |
michael@0 | 283 | |
michael@0 | 284 | EGLBoolean success = |
michael@0 | 285 | sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(), |
michael@0 | 286 | (EGLSurface)mSurface, |
michael@0 | 287 | LOCAL_EGL_BACK_BUFFER); |
michael@0 | 288 | |
michael@0 | 289 | if (success == LOCAL_EGL_FALSE) |
michael@0 | 290 | return false; |
michael@0 | 291 | |
michael@0 | 292 | mBound = false; |
michael@0 | 293 | return true; |
michael@0 | 294 | } |
michael@0 | 295 | |
michael@0 | 296 | void |
michael@0 | 297 | TextureImageEGL::DestroyEGLSurface(void) |
michael@0 | 298 | { |
michael@0 | 299 | if (!mSurface) |
michael@0 | 300 | return; |
michael@0 | 301 | |
michael@0 | 302 | sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface); |
michael@0 | 303 | mSurface = nullptr; |
michael@0 | 304 | } |
michael@0 | 305 | |
michael@0 | 306 | already_AddRefed<TextureImage> |
michael@0 | 307 | CreateTextureImageEGL(GLContext *gl, |
michael@0 | 308 | const gfx::IntSize& aSize, |
michael@0 | 309 | TextureImage::ContentType aContentType, |
michael@0 | 310 | GLenum aWrapMode, |
michael@0 | 311 | TextureImage::Flags aFlags, |
michael@0 | 312 | TextureImage::ImageFormat aImageFormat) |
michael@0 | 313 | { |
michael@0 | 314 | nsRefPtr<TextureImage> t = new gl::TiledTextureImage(gl, aSize, aContentType, aFlags, aImageFormat); |
michael@0 | 315 | return t.forget(); |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | already_AddRefed<TextureImage> |
michael@0 | 319 | TileGenFuncEGL(GLContext *gl, |
michael@0 | 320 | const nsIntSize& aSize, |
michael@0 | 321 | TextureImage::ContentType aContentType, |
michael@0 | 322 | TextureImage::Flags aFlags, |
michael@0 | 323 | TextureImage::ImageFormat aImageFormat) |
michael@0 | 324 | { |
michael@0 | 325 | gl->MakeCurrent(); |
michael@0 | 326 | |
michael@0 | 327 | GLuint texture; |
michael@0 | 328 | gl->fGenTextures(1, &texture); |
michael@0 | 329 | |
michael@0 | 330 | nsRefPtr<TextureImageEGL> teximage = |
michael@0 | 331 | new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, |
michael@0 | 332 | gl, aFlags, TextureImage::Created, aImageFormat); |
michael@0 | 333 | |
michael@0 | 334 | teximage->BindTexture(LOCAL_GL_TEXTURE0); |
michael@0 | 335 | |
michael@0 | 336 | GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR; |
michael@0 | 337 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter); |
michael@0 | 338 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter); |
michael@0 | 339 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); |
michael@0 | 340 | gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); |
michael@0 | 341 | |
michael@0 | 342 | return teximage.forget(); |
michael@0 | 343 | } |
michael@0 | 344 | |
michael@0 | 345 | } |
michael@0 | 346 | } |