コード例 #1
0
ファイル: imagpng.cpp プロジェクト: chromylei/third_party
// determine the kind of transparency we need for this image: if the only alpha
// values it has are 0 (transparent) and 0xff (opaque) then we can simply
// create a mask for it, we should be ok with a simple mask but otherwise we
// need a full blown alpha channel in wxImage
//
// parameters:
//      lines           raw PNG data
//      x, y            starting position
//      w, h            size of the image
//      numColBytes     number of colour bytes (1 for grey scale, 3 for RGB)
//                      (NB: alpha always follows the colour bytes)
Transparency
CheckTransparency(unsigned char **lines,
                  png_uint_32 x, png_uint_32 y, png_uint_32 w, png_uint_32 h,
                  size_t numColBytes)
{
    // suppose that a mask will suffice and check all the remaining alpha
    // values to see if it does
    for ( ; y < h; y++ )
    {
        // each pixel is numColBytes+1 bytes, offset into the current line by
        // the current x position
        unsigned const char *ptr = lines[y] + (x * (numColBytes + 1));

        for ( png_uint_32 x2 = x; x2 < w; x2++ )
        {
            // skip the grey or colour byte(s)
            ptr += numColBytes;

            unsigned char a2 = *ptr++;

            if ( !IsTransparent(a2) && !IsOpaque(a2) )
            {
                // not fully opaque nor fully transparent, hence need alpha
                return Transparency_Alpha;
            }
        }

        // during the next loop iteration check all the pixels in the row
        x = 0;
    }

    // mask will be enough
    return Transparency_Mask;
}
コード例 #2
0
DrawTargetCaptureImpl::DrawTargetCaptureImpl(BackendType aBackend,
                                             const IntSize& aSize,
                                             SurfaceFormat aFormat)
  : mSize(aSize),
    mSnapshot(nullptr),
    mStride(0),
    mSurfaceAllocationSize(0),
    mFlushBytes(0)
{
  RefPtr<DrawTarget> screenRefDT =
      gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();

  mFormat = aFormat;
  SetPermitSubpixelAA(IsOpaque(mFormat));
  if (aBackend == screenRefDT->GetBackendType()) {
    mRefDT = screenRefDT;
  } else {
    // This situation can happen if a blur operation decides to
    // use an unaccelerated path even if the system backend is
    // Direct2D.
    //
    // We don't really want to encounter the reverse scenario:
    // we shouldn't pick an accelerated backend if the system
    // backend is skia.
    if (aBackend == BackendType::DIRECT2D1_1) {
      gfxWarning() << "Creating a RefDT in DrawTargetCapture.";
    }

    // Create a 1x1 size ref dt to create assets
    // If we have to snapshot, we'll just create the real DT
    IntSize size(1, 1);
    mRefDT = Factory::CreateDrawTarget(aBackend, size, mFormat);
  }
}
コード例 #3
0
RasterImage::WillDrawOpaqueNow()
{
  if (!IsOpaque()) {
    return false;
  }

  if (mAnimationState) {
    // We never discard frames of animated images.
    return true;
  }

  // If we are not locked our decoded data could get discard at any time (ie
  // between the call to this function and when we are asked to draw), so we
  // have to return false if we are unlocked.
  if (IsUnlocked()) {
    return false;
  }

  LookupResult result =
    SurfaceCache::LookupBestMatch(ImageKey(this),
                                  RasterSurfaceKey(mSize,
                                                   DefaultSurfaceFlags(),
                                                   PlaybackType::eStatic));
  MatchType matchType = result.Type();
  if (matchType == MatchType::NOT_FOUND || matchType == MatchType::PENDING ||
      !result.Surface()->IsFinished()) {
    return false;
  }

  return true;
}
コード例 #4
0
ファイル: nsDisplayList.cpp プロジェクト: ahadzi/celtx
// Suitable for leaf items only, overridden by nsDisplayWrapList
PRBool
nsDisplayItem::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
                                  nsRegion* aVisibleRegion) {
  nsRect bounds = GetBounds(aBuilder);
  if (!aVisibleRegion->Intersects(bounds))
    return PR_FALSE;

  nsIFrame* f = GetUnderlyingFrame();
  NS_ASSERTION(f, "GetUnderlyingFrame() must return non-null for leaf items");
  PRBool isMoving = aBuilder->IsMovingFrame(f);

  if (IsOpaque(aBuilder)) {
    nsRect opaqueArea = bounds;
    if (isMoving) {
      // The display list should include items for both the before and after
      // states (see nsLayoutUtils::ComputeRepaintRegionForCopy. So the
      // only area we want to cover is the the area that was opaque in the
      // before state and in the after state.
      opaqueArea.IntersectRect(bounds - aBuilder->GetMoveDelta(), bounds);
    }
    aVisibleRegion->SimpleSubtract(opaqueArea);
  }

  return PR_TRUE;
}
コード例 #5
0
ファイル: container.cpp プロジェクト: doveiya/isilme
    void Container::Draw(GraphicsPtr graphics)
    {
        if (IsOpaque())
        {
            graphics->setColor(getBaseColor());
            graphics->fillRectangle(Rectangle(0, 0, GetWidth(), GetHeight()));
        }

        DrawChildren(graphics);
    }
コード例 #6
0
bool
DrawTargetCaptureImpl::Init(const IntSize& aSize, DrawTarget* aRefDT)
{
  if (!aRefDT) {
    return false;
  }

  mRefDT = aRefDT;

  mSize = aSize;
  mFormat = aRefDT->GetFormat();
  SetPermitSubpixelAA(IsOpaque(mFormat));
  return true;
}
コード例 #7
0
ファイル: imagpng.cpp プロジェクト: chromylei/third_party
// convert data from RGB to wxImage format
static
void CopyDataFromPNG(wxImage *image,
                     unsigned char **lines,
                     png_uint_32 width,
                     png_uint_32 height,
                     int color_type)
{
    Transparency transparency = Transparency_None;

    // only non NULL if transparency == Transparency_Alpha
    unsigned char *alpha = NULL;

    // RGB of the mask colour if transparency == Transparency_Mask
    // (but init them anyhow to avoid compiler warnings)
    unsigned char rMask = 0,
                  gMask = 0,
                  bMask = 0;

    unsigned char *ptrDst = image->GetData();
    if ( !(color_type & PNG_COLOR_MASK_COLOR) )
    {
        // grey image: GAGAGA... where G == grey component and A == alpha
        for ( png_uint_32 y = 0; y < height; y++ )
        {
            const unsigned char *ptrSrc = lines[y];
            for ( png_uint_32 x = 0; x < width; x++ )
            {
                unsigned char g = *ptrSrc++;
                unsigned char a = *ptrSrc++;

                // the first time we encounter a transparent pixel we must
                // decide about what to do about them
                if ( !IsOpaque(a) && transparency == Transparency_None )
                {
                    // we'll need at least the mask for this image and
                    // maybe even full alpha channel info: the former is
                    // only enough if we have alpha values of 0 and 0xff
                    // only, otherwisewe need the latter
                    transparency = CheckTransparency
                                   (
                                        lines,
                                        x, y,
                                        width, height,
                                        1
                                   );

                    if ( transparency == Transparency_Mask )
                    {
                        // let's choose this colour for the mask: this is
                        // not a problem here as all the other pixels are
                        // grey, i.e. R == G == B which is not the case for
                        // this one so no confusion is possible
                        rMask = 0xff;
                        gMask = 0;
                        bMask = 0xff;
                    }
                    else // transparency == Transparency_Alpha
                    {
                        alpha = InitAlpha(image, x, y);
                    }
                }

                switch ( transparency )
                {
                    case Transparency_Mask:
                        if ( IsTransparent(a) )
                        {
                            *ptrDst++ = rMask;
                            *ptrDst++ = gMask;
                            *ptrDst++ = bMask;
                            break;
                        }
                        // else: !transparent

                        // must be opaque then as otherwise we shouldn't be
                        // using the mask at all
                        wxASSERT_MSG( IsOpaque(a), wxT("logic error") );

                        // fall through

                    case Transparency_Alpha:
                        if ( alpha )
                            *alpha++ = a;
                        // fall through

                    case Transparency_None:
                        *ptrDst++ = g;
                        *ptrDst++ = g;
                        *ptrDst++ = g;
                        break;
                }
            }
        }
    }
    else // colour image: RGBRGB...
    {
        for ( png_uint_32 y = 0; y < height; y++ )
        {
            const unsigned char *ptrSrc = lines[y];
            for ( png_uint_32 x = 0; x < width; x++ )
            {
                unsigned char r = *ptrSrc++;
                unsigned char g = *ptrSrc++;
                unsigned char b = *ptrSrc++;
                unsigned char a = *ptrSrc++;

                // the logic here is the same as for the grey case except
                // where noted
                if ( !IsOpaque(a) && transparency == Transparency_None )
                {
                    transparency = CheckTransparency
                                   (
                                        lines,
                                        x, y,
                                        width, height,
                                        3
                                   );

                    if ( transparency == Transparency_Mask )
                    {
                        FindMaskColour(lines, width, height,
                                       rMask, gMask, bMask);
                    }
                    else // transparency == Transparency_Alpha
                    {
                        alpha = InitAlpha(image, x, y);
                    }

                }

                switch ( transparency )
                {
                    case Transparency_Mask:
                        if ( IsTransparent(a) )
                        {
                            *ptrDst++ = rMask;
                            *ptrDst++ = gMask;
                            *ptrDst++ = bMask;
                            break;
                        }
                        else // !transparent
                        {
                            // must be opaque then as otherwise we shouldn't be
                            // using the mask at all
                            wxASSERT_MSG( IsOpaque(a), wxT("logic error") );

                            // if we couldn't find a unique colour for the
                            // mask, we can have real pixels with the same
                            // value as the mask and it's better to slightly
                            // change their colour than to make them
                            // transparent
                            if ( r == rMask && g == gMask && b == bMask )
                            {
                                r++;
                            }
                        }

                        // fall through

                    case Transparency_Alpha:
                        if ( alpha )
                            *alpha++ = a;
                        // fall through

                    case Transparency_None:
                        *ptrDst++ = r;
                        *ptrDst++ = g;
                        *ptrDst++ = b;
                        break;
                }
            }
        }
    }

    if ( transparency == Transparency_Mask )
    {
        image->SetMaskColour(rMask, gMask, bMask);
    }
}
コード例 #8
0
ファイル: GSRendererDX.cpp プロジェクト: docbray/pcsx2-online
void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
	GSDrawingEnvironment& env = m_env;
	GSDrawingContext* context = m_context;

	const GSVector2i& rtsize = rt->GetSize();
	const GSVector2& rtscale = rt->GetScale();

	bool DATE = m_context->TEST.DATE && context->FRAME.PSM != PSM_PSMCT24;

	GSTexture* rtcopy = NULL;

	ASSERT(m_dev != NULL);

	GSDeviceDX* dev = (GSDeviceDX*)m_dev;

	if(DATE)
	{
		if(dev->HasStencil())
		{
			GSVector4 s = GSVector4(rtscale.x / rtsize.x, rtscale.y / rtsize.y);
			GSVector4 o = GSVector4(-1.0f, 1.0f);

			GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
			GSVector4 dst = src * 2.0f + o.xxxx();

			GSVertexPT1 vertices[] =
			{
				{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
				{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
				{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
				{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
			};

			dev->SetupDATE(rt, ds, vertices, m_context->TEST.DATM);
		}
		else
		{
			rtcopy = dev->CreateRenderTarget(rtsize.x, rtsize.y, false, rt->GetFormat());

			// I'll use VertexTrace when I consider it more trustworthy

			dev->CopyRect(rt, rtcopy, GSVector4i(rtsize).zwxy());
		}
	}

	//

	dev->BeginScene();

	// om

	GSDeviceDX::OMDepthStencilSelector om_dssel;

	if(context->TEST.ZTE)
	{
		om_dssel.ztst = context->TEST.ZTST;
		om_dssel.zwe = !context->ZBUF.ZMSK;
	}
	else
	{
		om_dssel.ztst = ZTST_ALWAYS;
	}

	if(m_fba)
	{
		om_dssel.fba = context->FBA.FBA;
	}

	GSDeviceDX::OMBlendSelector om_bsel;

	if(!IsOpaque())
	{
		om_bsel.abe = PRIM->ABE || PRIM->AA1 && m_vt.m_primclass == GS_LINE_CLASS;

		om_bsel.a = context->ALPHA.A;
		om_bsel.b = context->ALPHA.B;
		om_bsel.c = context->ALPHA.C;
		om_bsel.d = context->ALPHA.D;

		if(env.PABE.PABE)
		{
			if(om_bsel.a == 0 && om_bsel.b == 1 && om_bsel.c == 0 && om_bsel.d == 1)
			{
				// this works because with PABE alpha blending is on when alpha >= 0x80, but since the pixel shader
				// cannot output anything over 0x80 (== 1.0) blending with 0x80 or turning it off gives the same result

				om_bsel.abe = 0;
			}
			else
			{
				//Breath of Fire Dragon Quarter triggers this in battles. Graphics are fine though.
				//ASSERT(0);
			}
		}
	}

	om_bsel.wrgba = ~GSVector4i::load((int)context->FRAME.FBMSK).eq8(GSVector4i::xffffffff()).mask();

	// vs

	GSDeviceDX::VSSelector vs_sel;

	vs_sel.tme = PRIM->TME;
	vs_sel.fst = PRIM->FST;
	vs_sel.logz = dev->HasDepth32() ? 0 : m_logz ? 1 : 0;
	vs_sel.rtcopy = !!rtcopy;

	// The real GS appears to do no masking based on the Z buffer format and writing larger Z values
	// than the buffer supports seems to be an error condition on the real GS, causing it to crash.
	// We are probably receiving bad coordinates from VU1 in these cases.

	if(om_dssel.ztst >= ZTST_ALWAYS && om_dssel.zwe)
	{
		if(context->ZBUF.PSM == PSM_PSMZ24)
		{
			if(m_vt.m_max.p.z > 0xffffff)
			{
				ASSERT(m_vt.m_min.p.z > 0xffffff);
				// Fixme :Following conditional fixes some dialog frame in Wild Arms 3, but may not be what was intended.
				if (m_vt.m_min.p.z > 0xffffff)
				{
					vs_sel.bppz = 1;
					om_dssel.ztst = ZTST_ALWAYS;
				}
			}
		}
		else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
		{
			if(m_vt.m_max.p.z > 0xffff)
			{
				ASSERT(m_vt.m_min.p.z > 0xffff); // sfex capcom logo
				// Fixme : Same as above, I guess.
				if (m_vt.m_min.p.z > 0xffff)
				{
					vs_sel.bppz = 2;
					om_dssel.ztst = ZTST_ALWAYS;
				}
			}
		}
	}

	GSDeviceDX::VSConstantBuffer vs_cb;

	float sx = 2.0f * rtscale.x / (rtsize.x << 4);
	float sy = 2.0f * rtscale.y / (rtsize.y << 4);
	float ox = (float)(int)context->XYOFFSET.OFX;
	float oy = (float)(int)context->XYOFFSET.OFY;
	float ox2 = 2.0f * m_pixelcenter.x / rtsize.x;
	float oy2 = 2.0f * m_pixelcenter.y / rtsize.y;

	//This hack subtracts around half a pixel from OFX and OFY. (Cannot do this directly,
	//because DX10 and DX9 have a different pixel center.)
	//
	//The resulting shifted output aligns better with common blending / corona / blurring effects,
	//but introduces a few bad pixels on the edges.

	if(rt->LikelyOffset)
	{
		// DX9 has pixelcenter set to 0.0, so give it some value here

		if(m_pixelcenter.x == 0 && m_pixelcenter.y == 0) { ox2 = -0.0003f; oy2 = -0.0003f; }
		
		ox2 *= rt->OffsetHack_modx;
		oy2 *= rt->OffsetHack_mody;
	}

	vs_cb.VertexScale  = GSVector4(sx, -sy, ldexpf(1, -32), 0.0f);
	vs_cb.VertexOffset = GSVector4(ox * sx + ox2 + 1, -(oy * sy + oy2 + 1), 0.0f, -1.0f);

	// gs

	GSDeviceDX::GSSelector gs_sel;

	gs_sel.iip = PRIM->IIP;
	gs_sel.prim = m_vt.m_primclass;

	// ps

	GSDeviceDX::PSSelector ps_sel;
	GSDeviceDX::PSSamplerSelector ps_ssel;
	GSDeviceDX::PSConstantBuffer ps_cb;

	if(DATE)
	{
		if(dev->HasStencil())
		{
			om_dssel.date = 1;
		}
		else
		{
			ps_sel.date = 1 + context->TEST.DATM;
		}
	}

	if(env.COLCLAMP.CLAMP == 0 && /* hack */ !tex && PRIM->PRIM != GS_POINTLIST)
	{
		ps_sel.colclip = 1;
	}

	ps_sel.clr1 = om_bsel.IsCLR1();
	ps_sel.fba = context->FBA.FBA;
	ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
		
	if(UserHacks_AlphaHack) ps_sel.aout = 1;

	if(PRIM->FGE)
	{
		ps_sel.fog = 1;

		ps_cb.FogColor_AREF = GSVector4::rgba32(env.FOGCOL.u32[0]) / 255;
	}

	if(context->TEST.ATE)
	{
		ps_sel.atst = context->TEST.ATST;

		switch(ps_sel.atst)
		{
		case ATST_LESS:
			ps_cb.FogColor_AREF.a = (float)((int)context->TEST.AREF - 1);
			break;
		case ATST_GREATER:
			ps_cb.FogColor_AREF.a = (float)((int)context->TEST.AREF + 1);
			break;
		default:
			ps_cb.FogColor_AREF.a = (float)(int)context->TEST.AREF;
			break;
		}
	}
	else
	{
		ps_sel.atst = ATST_ALWAYS;
	}

	if(tex)
	{
		ps_sel.wms = context->CLAMP.WMS;
		ps_sel.wmt = context->CLAMP.WMT;
		ps_sel.fmt = tex->m_fmt;
		ps_sel.aem = env.TEXA.AEM;
		ps_sel.tfx = context->TEX0.TFX;
		ps_sel.tcc = context->TEX0.TCC;
		ps_sel.ltf = m_filter == 2 ? m_vt.IsLinear() : m_filter;
		ps_sel.rt = tex->m_target;

		int w = tex->m_texture->GetWidth();
		int h = tex->m_texture->GetHeight();

		int tw = (int)(1 << context->TEX0.TW);
		int th = (int)(1 << context->TEX0.TH);

		GSVector4 WH(tw, th, w, h);

		if(PRIM->FST)
		{
			vs_cb.TextureScale = GSVector4(1.0f / 16) / WH.xyxy();
			//Maybe better?
			//vs_cb.TextureScale = GSVector4(1.0f / 16) * GSVector4(tex->m_texture->GetScale()).xyxy() / WH.zwzw();
			ps_sel.fst = 1;
		}

		ps_cb.WH = WH;
		ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / WH.zwzw();
		ps_cb.MskFix = GSVector4i(context->CLAMP.MINU, context->CLAMP.MINV, context->CLAMP.MAXU, context->CLAMP.MAXV);

		GSVector4 clamp(ps_cb.MskFix);
		GSVector4 ta(env.TEXA & GSVector4i::x000000ff());

		ps_cb.MinMax = clamp / WH.xyxy();
		ps_cb.MinF_TA = (clamp + 0.5f).xyxy(ta) / WH.xyxy(GSVector4(255, 255));

		ps_ssel.tau = (context->CLAMP.WMS + 3) >> 1;
		ps_ssel.tav = (context->CLAMP.WMT + 3) >> 1;
		ps_ssel.ltf = ps_sel.ltf;
	}
	else
	{
コード例 #9
0
ファイル: imagpng.cpp プロジェクト: AaronDP/wxWidgets
// convert data from RGB to wxImage format
static
void CopyDataFromPNG(wxImage *image,
                     unsigned char **lines,
                     png_uint_32 width,
                     png_uint_32 height,
                     int color_type)
{
    // allocated on demand if we have any non-opaque pixels
    unsigned char *alpha = NULL;

    unsigned char *ptrDst = image->GetData();
    if ( !(color_type & PNG_COLOR_MASK_COLOR) )
    {
        // grey image: GAGAGA... where G == grey component and A == alpha
        for ( png_uint_32 y = 0; y < height; y++ )
        {
            const unsigned char *ptrSrc = lines[y];
            for ( png_uint_32 x = 0; x < width; x++ )
            {
                unsigned char g = *ptrSrc++;
                unsigned char a = *ptrSrc++;

                // the first time we encounter a transparent pixel we must
                // allocate alpha channel for the image
                if ( !IsOpaque(a) && !alpha )
                    alpha = InitAlpha(image, x, y);

                if ( alpha )
                    *alpha++ = a;

                *ptrDst++ = g;
                *ptrDst++ = g;
                *ptrDst++ = g;
            }
        }
    }
    else // colour image: RGBRGB...
    {
        for ( png_uint_32 y = 0; y < height; y++ )
        {
            const unsigned char *ptrSrc = lines[y];
            for ( png_uint_32 x = 0; x < width; x++ )
            {
                unsigned char r = *ptrSrc++;
                unsigned char g = *ptrSrc++;
                unsigned char b = *ptrSrc++;
                unsigned char a = *ptrSrc++;

                // the logic here is the same as for the grey case
                if ( !IsOpaque(a) && !alpha )
                    alpha = InitAlpha(image, x, y);

                if ( alpha )
                    *alpha++ = a;

                *ptrDst++ = r;
                *ptrDst++ = g;
                *ptrDst++ = b;
            }
        }
    }
}
コード例 #10
0
DrawableSurface
RasterImage::LookupFrame(const IntSize& aSize,
                         uint32_t aFlags,
                         PlaybackType aPlaybackType)
{
  MOZ_ASSERT(NS_IsMainThread());

  // If we're opaque, we don't need to care about premultiplied alpha, because
  // that can only matter for frames with transparency.
  if (IsOpaque()) {
    aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
  }

  IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags)
                        ? aSize : mSize;
  if (requestedSize.IsEmpty()) {
    return DrawableSurface();  // Can't decode to a surface of zero size.
  }

  LookupResult result =
    LookupFrameInternal(requestedSize, aFlags, aPlaybackType);

  if (!result && !mHasSize) {
    // We can't request a decode without knowing our intrinsic size. Give up.
    return DrawableSurface();
  }

  if (result.Type() == MatchType::NOT_FOUND ||
      result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND ||
      ((aFlags & FLAG_SYNC_DECODE) && !result)) {
    // We don't have a copy of this frame, and there's no decoder working on
    // one. (Or we're sync decoding and the existing decoder hasn't even started
    // yet.) Trigger decoding so it'll be available next time.
    MOZ_ASSERT(aPlaybackType != PlaybackType::eAnimated ||
               !mAnimationState || mAnimationState->KnownFrameCount() < 1,
               "Animated frames should be locked");

    Decode(requestedSize, aFlags, aPlaybackType);

    // If we can sync decode, we should already have the frame.
    if (aFlags & FLAG_SYNC_DECODE) {
      result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType);
    }
  }

  if (!result) {
    // We still weren't able to get a frame. Give up.
    return DrawableSurface();
  }

  if (result.Surface()->GetCompositingFailed()) {
    return DrawableSurface();
  }

  MOZ_ASSERT(!result.Surface()->GetIsPaletted(),
             "Should not have a paletted frame");

  // Sync decoding guarantees that we got the frame, but if it's owned by an
  // async decoder that's currently running, the contents of the frame may not
  // be available yet. Make sure we get everything.
  if (mHasSourceData && (aFlags & FLAG_SYNC_DECODE)) {
    result.Surface()->WaitUntilFinished();
  }

  // If we could have done some decoding in this function we need to check if
  // that decoding encountered an error and hence aborted the surface. We want
  // to avoid calling IsAborted if we weren't passed any sync decode flag because
  // IsAborted acquires the monitor for the imgFrame.
  if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) &&
    result.Surface()->IsAborted()) {
    return DrawableSurface();
  }

  return Move(result.Surface());
}
コード例 #11
0
NS_IMETHODIMP
RasterImage::Decode(const IntSize& aSize,
                    uint32_t aFlags,
                    PlaybackType aPlaybackType)
{
  MOZ_ASSERT(NS_IsMainThread());

  if (mError) {
    return NS_ERROR_FAILURE;
  }

  // If we don't have a size yet, we can't do any other decoding.
  if (!mHasSize) {
    mWantFullDecode = true;
    return NS_OK;
  }

  // We're about to decode again, which may mean that some of the previous sizes
  // we've decoded at aren't useful anymore. We can allow them to expire from
  // the cache by unlocking them here. When the decode finishes, it will send an
  // invalidation that will cause all instances of this image to redraw. If this
  // image is locked, any surfaces that are still useful will become locked
  // again when LookupFrame touches them, and the remainder will eventually
  // expire.
  SurfaceCache::UnlockEntries(ImageKey(this));

  // Determine which flags we need to decode this image with.
  DecoderFlags decoderFlags = DefaultDecoderFlags();
  if (aFlags & FLAG_ASYNC_NOTIFY) {
    decoderFlags |= DecoderFlags::ASYNC_NOTIFY;
  }
  if (mTransient) {
    decoderFlags |= DecoderFlags::IMAGE_IS_TRANSIENT;
  }
  if (mHasBeenDecoded) {
    decoderFlags |= DecoderFlags::IS_REDECODE;
  }

  SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags);
  if (IsOpaque()) {
    // If there's no transparency, it doesn't matter whether we premultiply
    // alpha or not.
    surfaceFlags &= ~SurfaceFlags::NO_PREMULTIPLY_ALPHA;
  }

  // Create a decoder.
  RefPtr<IDecodingTask> task;
  if (mAnimationState && aPlaybackType == PlaybackType::eAnimated) {
    task = DecoderFactory::CreateAnimationDecoder(mDecoderType, WrapNotNull(this),
                                                  mSourceBuffer, mSize,
                                                  decoderFlags, surfaceFlags);
  } else {
    task = DecoderFactory::CreateDecoder(mDecoderType, WrapNotNull(this),
                                         mSourceBuffer, mSize, aSize,
                                         decoderFlags, surfaceFlags,
                                         mRequestedSampleSize);
  }

  // Make sure DecoderFactory was able to create a decoder successfully.
  if (!task) {
    return NS_ERROR_FAILURE;
  }

  mDecodeCount++;

  // We're ready to decode; start the decoder.
  LaunchDecodingTask(task, this, aFlags, mHasSourceData);
  return NS_OK;
}