mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
Merge branch 'gre-tracking' into tracking
This commit is contained in:
commit
38f14f9adc
161 changed files with 10773 additions and 13788 deletions
|
|
@ -108,6 +108,7 @@ public:
|
|||
|
||||
void SetInsertionPointChanged() { mInsertionPointChanged = true; }
|
||||
|
||||
nsXBLBinding* GetAssociatedBinding() { return mAssociatedBinding; }
|
||||
void SetAssociatedBinding(nsXBLBinding* aBinding) { mAssociatedBinding = aBinding; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
|
|
|||
|
|
@ -718,19 +718,10 @@ nsAttrAndChildArray::MappedAttrCount() const
|
|||
return mImpl && mImpl->mMappedAttrs ? (uint32_t)mImpl->mMappedAttrs->Count() : 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument)
|
||||
{
|
||||
nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
|
||||
RefPtr<nsMappedAttributes> mapped = GetModifiableMapped(aContent, sheet, false, 0);
|
||||
return MakeMappedUnique(mapped);
|
||||
}
|
||||
|
||||
nsMappedAttributes*
|
||||
nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
|
||||
nsHTMLStyleSheet* aSheet,
|
||||
bool aWillAddAttr,
|
||||
int32_t aAttrCount)
|
||||
bool aWillAddAttr)
|
||||
{
|
||||
if (mImpl && mImpl->mMappedAttrs) {
|
||||
return mImpl->mMappedAttrs->Clone(aWillAddAttr);
|
||||
|
|
@ -740,7 +731,7 @@ nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
|
|||
|
||||
nsMapRuleToAttributesFunc mapRuleFunc =
|
||||
aContent->GetAttributeMappingFunction();
|
||||
return new (aAttrCount) nsMappedAttributes(aSheet, mapRuleFunc);
|
||||
return new nsMappedAttributes(aSheet, mapRuleFunc);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
|||
|
|
@ -144,9 +144,6 @@ public:
|
|||
return MappedAttrCount();
|
||||
}
|
||||
|
||||
// Force this to have mapped attributes, even if those attributes are empty.
|
||||
nsresult ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument);
|
||||
|
||||
private:
|
||||
nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
|
||||
nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;
|
||||
|
|
@ -160,8 +157,7 @@ private:
|
|||
nsMappedAttributes*
|
||||
GetModifiableMapped(nsMappedAttributeElement* aContent,
|
||||
nsHTMLStyleSheet* aSheet,
|
||||
bool aWillAddAttr,
|
||||
int32_t aAttrCount = 1);
|
||||
bool aWillAddAttr);
|
||||
nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
|
||||
|
||||
uint32_t AttrSlotsSize() const
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "nsIAnimationObserver.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
|
||||
class nsDOMMutationObserver;
|
||||
using mozilla::dom::MutationObservingInfo;
|
||||
|
|
@ -599,11 +600,7 @@ protected:
|
|||
|
||||
bool Suppressed()
|
||||
{
|
||||
if (mOwner) {
|
||||
nsCOMPtr<nsIDocument> d = mOwner->GetExtantDoc();
|
||||
return d && d->IsInSyncOperation();
|
||||
}
|
||||
return false;
|
||||
return mOwner && nsGlobalWindow::Cast(mOwner)->IsInSyncOperation();
|
||||
}
|
||||
|
||||
static void HandleMutationsInternal(mozilla::AutoSlowOperation& aAso);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
#include "nsGlobalWindow.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsView.h"
|
||||
#include "GroupedSHistory.h"
|
||||
#include "PartialSHistory.h"
|
||||
|
|
@ -936,8 +935,6 @@ nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
|
|||
RefPtr<nsPresContext> presContext;
|
||||
mDocShell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext)
|
||||
// rebuild, because now the same nsMappedAttributes* will produce
|
||||
// a different style
|
||||
presContext->RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1134,6 +1134,7 @@ GK_ATOM(scrollbarDownBottom, "scrollbar-down-bottom")
|
|||
GK_ATOM(scrollbarDownTop, "scrollbar-down-top")
|
||||
GK_ATOM(scrollbarUpBottom, "scrollbar-up-bottom")
|
||||
GK_ATOM(scrollbarUpTop, "scrollbar-up-top")
|
||||
GK_ATOM(scrollbarwidth, "scrollbarwidth")
|
||||
GK_ATOM(scrollbox, "scrollbox")
|
||||
GK_ATOM(scrollcorner, "scrollcorner")
|
||||
GK_ATOM(scrolling, "scrolling")
|
||||
|
|
|
|||
|
|
@ -1224,6 +1224,12 @@ public:
|
|||
already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
|
||||
|
||||
mozilla::dom::Performance* GetPerformance();
|
||||
|
||||
virtual bool IsInSyncOperation() override
|
||||
{
|
||||
return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Web IDL helpers
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,20 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
|
||||
using mozilla::AutoSlowOperation;
|
||||
using mozilla::CycleCollectedJSContext;
|
||||
using mozilla::ErrorResult;
|
||||
using mozilla::IgnoredErrorResult;
|
||||
using mozilla::MicroTaskRunnable;
|
||||
using mozilla::dom::VoidFunction;
|
||||
|
||||
nsIGlobalObject::~nsIGlobalObject()
|
||||
{
|
||||
UnlinkHostObjectURIs();
|
||||
|
|
@ -110,3 +120,31 @@ nsIGlobalObject::TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb)
|
|||
nsHostObjectProtocolHandler::Traverse(mHostObjectURIs[index], aCb);
|
||||
}
|
||||
}
|
||||
|
||||
class QueuedMicrotask : public MicroTaskRunnable {
|
||||
public:
|
||||
QueuedMicrotask(nsIGlobalObject* aGlobal, VoidFunction& aCallback)
|
||||
: mGlobal(aGlobal)
|
||||
, mCallback(&aCallback)
|
||||
{}
|
||||
|
||||
/* unsafe */
|
||||
void Run(AutoSlowOperation& aAso) final {
|
||||
IgnoredErrorResult rv;
|
||||
mCallback->Call(static_cast<ErrorResult&>(rv));
|
||||
}
|
||||
|
||||
bool Suppressed() final { return mGlobal->IsInSyncOperation(); }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<VoidFunction> mCallback;
|
||||
};
|
||||
|
||||
void nsIGlobalObject::QueueMicrotask(VoidFunction& aCallback) {
|
||||
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
|
||||
if (context) {
|
||||
RefPtr<MicroTaskRunnable> mt = new QueuedMicrotask(this, aCallback);
|
||||
context->DispatchMicroTaskRunnable(mt.forget());
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,13 @@ class nsCString;
|
|||
class nsCycleCollectionTraversalCallback;
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla{
|
||||
namespace dom{
|
||||
class VoidFunction;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class nsIGlobalObject : public nsISupports
|
||||
{
|
||||
nsTArray<nsCString> mHostObjectURIs;
|
||||
|
|
@ -72,6 +79,10 @@ public:
|
|||
void UnlinkHostObjectURIs();
|
||||
void TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb);
|
||||
|
||||
virtual bool IsInSyncOperation() { return false; }
|
||||
|
||||
void QueueMicrotask(mozilla::dom::VoidFunction& aCallback);
|
||||
|
||||
protected:
|
||||
virtual ~nsIGlobalObject();
|
||||
|
||||
|
|
|
|||
|
|
@ -1652,6 +1652,9 @@ private:
|
|||
ParserHasNotified,
|
||||
// Sets if the node is apz aware or we have apz aware listeners.
|
||||
MayBeApzAware,
|
||||
// Set if this node has at some point (and may still have)
|
||||
// display:none or display:contents children.
|
||||
NodeMayHaveChildrenWithLayoutBoxesDisabled,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
|
|
@ -1790,6 +1793,20 @@ public:
|
|||
{
|
||||
return GetBoolFlag(MayBeApzAware);
|
||||
}
|
||||
|
||||
void SetMayHaveChildrenWithLayoutBoxesDisabled()
|
||||
{
|
||||
SetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
|
||||
}
|
||||
void UnsetMayHaveChildrenWithLayoutBoxesDisabled()
|
||||
{
|
||||
ClearBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
|
||||
}
|
||||
bool MayHaveChildrenWithLayoutBoxesDisabled() const
|
||||
{
|
||||
return GetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
|
||||
void SetIsInDocument() { SetBoolFlag(IsInDocument); }
|
||||
|
|
|
|||
|
|
@ -61,17 +61,11 @@ nsMappedAttributes::Clone(bool aWillAddAttr)
|
|||
|
||||
void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW
|
||||
{
|
||||
size_t size = aSize + aAttrCount * sizeof(InternalAttr);
|
||||
NS_ASSERTION(aAttrCount > 0, "zero-attribute nsMappedAttributes requested");
|
||||
|
||||
// aSize will include the mAttrs buffer so subtract that.
|
||||
// We don't want to under-allocate, however, so do not subtract
|
||||
// if we have zero attributes. The zero attribute case only happens
|
||||
// for <body>'s mapped attributes
|
||||
if (aAttrCount != 0) {
|
||||
size -= sizeof(void*[1]);
|
||||
}
|
||||
|
||||
void* newAttrs = ::operator new(size);
|
||||
void* newAttrs = ::operator new(aSize - sizeof(void*[1]) +
|
||||
aAttrCount * sizeof(InternalAttr));
|
||||
|
||||
#ifdef DEBUG
|
||||
static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
|
||||
|
|
|
|||
|
|
@ -751,6 +751,8 @@ EventListenerManager::SetEventHandler(nsIAtom* aName,
|
|||
bool aPermitUntrustedEvents,
|
||||
Element* aElement)
|
||||
{
|
||||
auto removeEventHandler = MakeScopeExit([&] { RemoveEventHandler(aName, EmptyString()); });
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsIScriptGlobalObject> global =
|
||||
GetScriptGlobalAndDocument(getter_AddRefs(doc));
|
||||
|
|
@ -825,6 +827,8 @@ EventListenerManager::SetEventHandler(nsIAtom* aName,
|
|||
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_STATE(global->GetGlobalJSObject());
|
||||
|
||||
removeEventHandler.release();
|
||||
|
||||
Listener* listener = SetEventHandlerInternal(aName,
|
||||
EmptyString(),
|
||||
TypedEventHandler(),
|
||||
|
|
|
|||
|
|
@ -27,8 +27,180 @@ namespace dom {
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
BodyRule::BodyRule(HTMLBodyElement* aPart)
|
||||
: mPart(aPart)
|
||||
{
|
||||
}
|
||||
|
||||
BodyRule::~BodyRule()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(BodyRule, nsIStyleRule)
|
||||
|
||||
/* virtual */ void
|
||||
BodyRule::MapRuleInfoInto(nsRuleData* aData)
|
||||
{
|
||||
if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) || !mPart)
|
||||
return; // We only care about margins.
|
||||
|
||||
int32_t bodyMarginWidth = -1;
|
||||
int32_t bodyMarginHeight = -1;
|
||||
int32_t bodyTopMargin = -1;
|
||||
int32_t bodyBottomMargin = -1;
|
||||
int32_t bodyLeftMargin = -1;
|
||||
int32_t bodyRightMargin = -1;
|
||||
|
||||
// check the mode (fortunately, the ruleData has a presContext for us to use!)
|
||||
NS_ASSERTION(aData->mPresContext, "null presContext in ruleNode was unexpected");
|
||||
nsCompatibility mode = aData->mPresContext->CompatibilityMode();
|
||||
|
||||
|
||||
const nsAttrValue* value;
|
||||
if (mPart->GetAttrCount() > 0) {
|
||||
// if marginwidth/marginheight are set, reflect them as 'margin'
|
||||
value = mPart->GetParsedAttr(nsGkAtoms::marginwidth);
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
bodyMarginWidth = value->GetIntegerValue();
|
||||
if (bodyMarginWidth < 0) bodyMarginWidth = 0;
|
||||
nsCSSValue* marginLeft = aData->ValueForMarginLeft();
|
||||
if (marginLeft->GetUnit() == eCSSUnit_Null)
|
||||
marginLeft->SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
|
||||
nsCSSValue* marginRight = aData->ValueForMarginRight();
|
||||
if (marginRight->GetUnit() == eCSSUnit_Null)
|
||||
marginRight->SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
value = mPart->GetParsedAttr(nsGkAtoms::marginheight);
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
bodyMarginHeight = value->GetIntegerValue();
|
||||
if (bodyMarginHeight < 0) bodyMarginHeight = 0;
|
||||
nsCSSValue* marginTop = aData->ValueForMarginTop();
|
||||
if (marginTop->GetUnit() == eCSSUnit_Null)
|
||||
marginTop->SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
|
||||
nsCSSValue* marginBottom = aData->ValueForMarginBottom();
|
||||
if (marginBottom->GetUnit() == eCSSUnit_Null)
|
||||
marginBottom->SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
// topmargin (IE-attribute)
|
||||
value = mPart->GetParsedAttr(nsGkAtoms::topmargin);
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
bodyTopMargin = value->GetIntegerValue();
|
||||
if (bodyTopMargin < 0) bodyTopMargin = 0;
|
||||
nsCSSValue* marginTop = aData->ValueForMarginTop();
|
||||
if (marginTop->GetUnit() == eCSSUnit_Null)
|
||||
marginTop->SetFloatValue((float)bodyTopMargin, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
// bottommargin (IE-attribute)
|
||||
value = mPart->GetParsedAttr(nsGkAtoms::bottommargin);
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
bodyBottomMargin = value->GetIntegerValue();
|
||||
if (bodyBottomMargin < 0) bodyBottomMargin = 0;
|
||||
nsCSSValue* marginBottom = aData->ValueForMarginBottom();
|
||||
if (marginBottom->GetUnit() == eCSSUnit_Null)
|
||||
marginBottom->SetFloatValue((float)bodyBottomMargin, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
// leftmargin (IE-attribute)
|
||||
value = mPart->GetParsedAttr(nsGkAtoms::leftmargin);
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
bodyLeftMargin = value->GetIntegerValue();
|
||||
if (bodyLeftMargin < 0) bodyLeftMargin = 0;
|
||||
nsCSSValue* marginLeft = aData->ValueForMarginLeft();
|
||||
if (marginLeft->GetUnit() == eCSSUnit_Null)
|
||||
marginLeft->SetFloatValue((float)bodyLeftMargin, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
// rightmargin (IE-attribute)
|
||||
value = mPart->GetParsedAttr(nsGkAtoms::rightmargin);
|
||||
if (value && value->Type() == nsAttrValue::eInteger) {
|
||||
bodyRightMargin = value->GetIntegerValue();
|
||||
if (bodyRightMargin < 0) bodyRightMargin = 0;
|
||||
nsCSSValue* marginRight = aData->ValueForMarginRight();
|
||||
if (marginRight->GetUnit() == eCSSUnit_Null)
|
||||
marginRight->SetFloatValue((float)bodyRightMargin, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if marginwidth or marginheight is set in the <frame> and not set in the <body>
|
||||
// reflect them as margin in the <body>
|
||||
if (bodyMarginWidth == -1 || bodyMarginHeight == -1) {
|
||||
nsCOMPtr<nsIDocShell> docShell(aData->mPresContext->GetDocShell());
|
||||
if (docShell) {
|
||||
nscoord frameMarginWidth=-1; // default value
|
||||
nscoord frameMarginHeight=-1; // default value
|
||||
docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set
|
||||
docShell->GetMarginHeight(&frameMarginHeight);
|
||||
if ((frameMarginWidth >= 0) && (bodyMarginWidth == -1)) { // set in <frame> & not in <body>
|
||||
if (eCompatibility_NavQuirks == mode) {
|
||||
if ((bodyMarginHeight == -1) && (0 > frameMarginHeight)) // nav quirk
|
||||
frameMarginHeight = 0;
|
||||
}
|
||||
}
|
||||
if ((frameMarginHeight >= 0) && (bodyMarginHeight == -1)) { // set in <frame> & not in <body>
|
||||
if (eCompatibility_NavQuirks == mode) {
|
||||
if ((bodyMarginWidth == -1) && (0 > frameMarginWidth)) // nav quirk
|
||||
frameMarginWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((bodyMarginWidth == -1) && (frameMarginWidth >= 0)) {
|
||||
nsCSSValue* marginLeft = aData->ValueForMarginLeft();
|
||||
if (marginLeft->GetUnit() == eCSSUnit_Null)
|
||||
marginLeft->SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
|
||||
nsCSSValue* marginRight = aData->ValueForMarginRight();
|
||||
if (marginRight->GetUnit() == eCSSUnit_Null)
|
||||
marginRight->SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
if ((bodyMarginHeight == -1) && (frameMarginHeight >= 0)) {
|
||||
nsCSSValue* marginTop = aData->ValueForMarginTop();
|
||||
if (marginTop->GetUnit() == eCSSUnit_Null)
|
||||
marginTop->SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
|
||||
nsCSSValue* marginBottom = aData->ValueForMarginBottom();
|
||||
if (marginBottom->GetUnit() == eCSSUnit_Null)
|
||||
marginBottom->SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
BodyRule::MightMapInheritedStyleData()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
BodyRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue)
|
||||
{
|
||||
MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* virtual */ void
|
||||
BodyRule::List(FILE* out, int32_t aIndent) const
|
||||
{
|
||||
nsAutoCString indent;
|
||||
for (int32_t index = aIndent; --index >= 0; ) {
|
||||
indent.AppendLiteral(" ");
|
||||
}
|
||||
fprintf_stderr(out, "%s[body rule] {}\n", indent.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
HTMLBodyElement::~HTMLBodyElement()
|
||||
{
|
||||
if (mContentStyleRule) {
|
||||
mContentStyleRule->mPart = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
|
@ -175,6 +347,17 @@ HTMLBodyElement::ParseAttribute(int32_t aNamespaceID,
|
|||
aResult);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLBodyElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
if (mContentStyleRule) {
|
||||
mContentStyleRule->mPart = nullptr;
|
||||
mContentStyleRule = nullptr;
|
||||
}
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData)
|
||||
|
|
@ -230,6 +413,22 @@ HTMLBodyElement::GetAttributeMappingFunction() const
|
|||
return &MapAttributesIntoRule;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLBodyElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
|
||||
|
||||
if (!mContentStyleRule && IsInUncomposedDoc()) {
|
||||
// XXXbz should this use OwnerDoc() or GetComposedDoc()?
|
||||
// sXBL/XBL2 issue!
|
||||
mContentStyleRule = new BodyRule(this);
|
||||
}
|
||||
if (aRuleWalker && mContentStyleRule) {
|
||||
aRuleWalker->Forward(mContentStyleRule);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
HTMLBodyElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||
{
|
||||
|
|
@ -238,12 +437,12 @@ HTMLBodyElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
|||
{ &nsGkAtoms::vlink },
|
||||
{ &nsGkAtoms::alink },
|
||||
{ &nsGkAtoms::text },
|
||||
// These aren't mapped through attribute mapping, but they are
|
||||
// mapped through a style rule, so it is attribute dependent style.
|
||||
// XXXldb But we don't actually replace the body rule when we have
|
||||
// dynamic changes...
|
||||
{ &nsGkAtoms::marginwidth },
|
||||
{ &nsGkAtoms::marginheight },
|
||||
{ &nsGkAtoms::topmargin },
|
||||
{ &nsGkAtoms::rightmargin },
|
||||
{ &nsGkAtoms::bottommargin },
|
||||
{ &nsGkAtoms::leftmargin },
|
||||
{ nullptr },
|
||||
};
|
||||
|
||||
|
|
@ -292,37 +491,6 @@ HTMLBodyElement::IsEventAttributeName(nsIAtom *aName)
|
|||
EventNameType_HTMLBodyOrFramesetOnly);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
bool aCompileEventHandlers)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return mAttrsAndChildren.ForceMapped(this, OwnerDoc());
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue, bool aNotify)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID,
|
||||
aName, aValue, aOldValue,
|
||||
aNotify);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// if the last mapped attribute was removed, don't clear the
|
||||
// nsMappedAttributes, our style can still depend on the containing frame element
|
||||
if (!aValue && IsAttributeMapped(aName)) {
|
||||
nsresult rv = mAttrsAndChildren.ForceMapped(this, OwnerDoc());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
|
||||
// nsGenericHTMLElement::GetOnError returns
|
||||
// already_AddRefed<EventHandlerNonNull> while other getters return
|
||||
|
|
|
|||
|
|
@ -14,6 +14,28 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class OnBeforeUnloadEventHandlerNonNull;
|
||||
class HTMLBodyElement;
|
||||
|
||||
class BodyRule: public nsIStyleRule
|
||||
{
|
||||
virtual ~BodyRule();
|
||||
|
||||
public:
|
||||
explicit BodyRule(HTMLBodyElement* aPart);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIStyleRule interface
|
||||
virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
|
||||
virtual bool MightMapInheritedStyleData() override;
|
||||
virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue) override;
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
|
||||
#endif
|
||||
|
||||
HTMLBodyElement* mPart; // not ref-counted, cleared by content
|
||||
};
|
||||
|
||||
class HTMLBodyElement final : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLBodyElement
|
||||
|
|
@ -102,29 +124,23 @@ public:
|
|||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
nsAttrValue& aResult) override;
|
||||
virtual void UnbindFromTree(bool aDeep = true,
|
||||
bool aNullParent = true) override;
|
||||
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
|
||||
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
||||
virtual already_AddRefed<nsIEditor> GetAssociatedEditor() override;
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||
|
||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
bool aCompileEventHandlers) override;
|
||||
/**
|
||||
* Called when an attribute has just been changed
|
||||
*/
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue,
|
||||
bool aNotify) override;
|
||||
|
||||
protected:
|
||||
virtual ~HTMLBodyElement();
|
||||
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
RefPtr<BodyRule> mContentStyleRule;
|
||||
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,9 @@ HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
|||
nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (nsMappedAttributes* tableInheritedAttributes = GetMappedAttributesInheritedFromTable()) {
|
||||
if (HTMLTableElement* table = GetTable()) {
|
||||
nsMappedAttributes* tableInheritedAttributes =
|
||||
table->GetAttributesMappedForCell();
|
||||
if (tableInheritedAttributes) {
|
||||
aRuleWalker->Forward(tableInheritedAttributes);
|
||||
}
|
||||
|
|
@ -114,16 +116,6 @@ HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMappedAttributes*
|
||||
HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const
|
||||
{
|
||||
if (HTMLTableElement* table = GetTable()) {
|
||||
return table->GetAttributesMappedForCell();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableCellElement::SetAbbr(const nsAString& aAbbr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -147,8 +147,6 @@ public:
|
|||
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
|
||||
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
||||
// Get mapped attributes of ancestor table, if any
|
||||
nsMappedAttributes* GetMappedAttributesInheritedFromTable() const;
|
||||
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ TableRowsCollection::ParentDestroyed()
|
|||
|
||||
HTMLTableElement::HTMLTableElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mTableInheritedAttributes(nullptr)
|
||||
mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
|
||||
{
|
||||
SetHasWeirdParserInsertionMode();
|
||||
}
|
||||
|
|
@ -911,15 +911,20 @@ MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
|||
nsMappedAttributes*
|
||||
HTMLTableElement::GetAttributesMappedForCell()
|
||||
{
|
||||
return mTableInheritedAttributes;
|
||||
if (mTableInheritedAttributes) {
|
||||
if (mTableInheritedAttributes == TABLE_ATTRS_DIRTY)
|
||||
BuildInheritedAttributes();
|
||||
if (mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
|
||||
return mTableInheritedAttributes;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLTableElement::BuildInheritedAttributes()
|
||||
{
|
||||
NS_ASSERTION(!mTableInheritedAttributes,
|
||||
NS_ASSERTION(mTableInheritedAttributes == TABLE_ATTRS_DIRTY,
|
||||
"potential leak, plus waste of work");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsIDocument *document = GetComposedDoc();
|
||||
nsHTMLStyleSheet* sheet = document ?
|
||||
document->GetAttributeStyleSheet() : nullptr;
|
||||
|
|
@ -956,7 +961,10 @@ HTMLTableElement::BuildInheritedAttributes()
|
|||
void
|
||||
HTMLTableElement::ReleaseInheritedAttributes()
|
||||
{
|
||||
NS_IF_RELEASE(mTableInheritedAttributes);
|
||||
if (mTableInheritedAttributes &&
|
||||
mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
|
||||
NS_RELEASE(mTableInheritedAttributes);
|
||||
mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
@ -965,12 +973,9 @@ HTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
bool aCompileEventHandlers)
|
||||
{
|
||||
ReleaseInheritedAttributes();
|
||||
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
BuildInheritedAttributes();
|
||||
return NS_OK;
|
||||
return nsGenericHTMLElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1)
|
||||
|
||||
class TableRowsCollection;
|
||||
|
||||
class HTMLTableElement final : public nsGenericHTMLElement
|
||||
|
|
@ -219,6 +221,8 @@ protected:
|
|||
|
||||
RefPtr<nsContentList> mTBodies;
|
||||
RefPtr<TableRowsCollection> mRows;
|
||||
// Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
|
||||
// to be recalculated.
|
||||
nsMappedAttributes *mTableInheritedAttributes;
|
||||
void BuildInheritedAttributes();
|
||||
void ReleaseInheritedAttributes();
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
|
||||
# autofocus attribute (we can't test with mochitests)
|
||||
# many stylo intermittents in files below
|
||||
# include autofocus/reftest-stylo.list
|
||||
# include toblob-todataurl/reftest-stylo.list
|
||||
|
||||
skip-if(B2G) == 41464-1a.html 41464-1a.html
|
||||
skip-if(B2G) == 41464-1b.html 41464-1b.html
|
||||
== 52019-1.html 52019-1.html
|
||||
== 82711-1.html 82711-1.html
|
||||
== 82711-2.html 82711-2.html
|
||||
== 82711-1-ref.html 82711-1-ref.html
|
||||
random == 468263-1a.html 468263-1a.html
|
||||
random == 468263-1b.html 468263-1b.html
|
||||
random == 468263-1c.html 468263-1c.html
|
||||
random == 468263-1d.html 468263-1d.html
|
||||
random == 468263-2.html 468263-2.html
|
||||
random == 468263-2.html 468263-2.html
|
||||
== 484200-1.html 484200-1.html
|
||||
== 485377.html 485377.html
|
||||
== 557840.html 557840.html
|
||||
== 560059-video-dimensions.html 560059-video-dimensions.html
|
||||
== 573322-quirks.html 573322-quirks.html
|
||||
== 573322-no-quirks.html 573322-no-quirks.html
|
||||
# == 596455-1a.html 596455-1a.html
|
||||
== 596455-1b.html 596455-1b.html
|
||||
== 596455-2a.html 596455-2a.html
|
||||
== 596455-2b.html 596455-2b.html
|
||||
== 610935.html 610935.html
|
||||
== 649134-1.html 649134-1.html
|
||||
skip-if(Android||B2G) == 649134-2.html 649134-2.html
|
||||
|
||||
== bug448564-1_malformed.html bug448564-1_malformed.html
|
||||
== bug448564-1_malformed.html bug448564-1_malformed.html
|
||||
|
||||
== bug448564-4a.html bug448564-4a.html
|
||||
== bug502168-1_malformed.html bug502168-1_malformed.html
|
||||
|
||||
random == responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit.html
|
||||
|
||||
# Test that image documents taken into account CSS properties like
|
||||
# image-orientation when determining the size of the image.
|
||||
# (Fuzzy necessary due to pixel-wise comparison of different JPEGs.
|
||||
# The vast majority of the fuzziness comes from Linux and WinXP.)
|
||||
skip == bug917595-iframe-1.html bug917595-iframe-1.html
|
||||
skip == bug917595-exif-rotated.jpg bug917595-exif-rotated.jpg
|
||||
# bug 1060869
|
||||
# Bug 1150490 disabling on Mulet as on B2G
|
||||
|
||||
# Test support for SVG-as-image in <picture> elements.
|
||||
== bug1106522-1.html bug1106522-1.html
|
||||
== bug1106522-2.html bug1106522-2.html
|
||||
|
||||
== href-attr-change-restyles.html href-attr-change-restyles.html
|
||||
== figure.html figure.html
|
||||
== pre-1.html pre-1.html
|
||||
== table-border-1.html table-border-1.html
|
||||
== table-border-2.html table-border-2.html
|
||||
== table-border-2.html table-border-2.html
|
||||
|
||||
# Test imageset is using permissions.default.image
|
||||
pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html
|
||||
pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html
|
||||
|
||||
# Test video with rotation information can be rotated.
|
||||
== bug1228601-video-rotation-90.html bug1228601-video-rotation-90.html
|
||||
|
||||
# Test that dynamically setting body margin attributes updates style appropriately
|
||||
== body-topmargin-dynamic.html body-topmargin-dynamic.html
|
||||
|
||||
# Test that dynamically removing a nonmargin mapped attribute does not
|
||||
# destroy margins inherited from the frame.
|
||||
== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint.html
|
||||
4
dom/html/test/body-margin-test/child.html
Normal file
4
dom/html/test/body-margin-test/child.html
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<HTML>
|
||||
<BODY BGCOLOR="#ffffff" TEXT="#000000">
|
||||
<A HREF="/internal-url-removed/" TARGET="_top"><IMG SRC="fruit.jpg" ALT="" BORDER=0 WIDTH="800" HEIGHT="600"></A>
|
||||
</BODY></HTML>
|
||||
BIN
dom/html/test/body-margin-test/fruit.jpg
Normal file
BIN
dom/html/test/body-margin-test/fruit.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
9
dom/html/test/body-margin-test/test-body.html
Normal file
9
dom/html/test/body-margin-test/test-body.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#000099" TEXT="#000000" TOPMARGIN=0 BOTTOMMARGIN=0 LEFTMARGIN=0 RIGHTMARGIN=0 MARGINWIDTH=0 MARGINHEIGHT=0>
|
||||
<img src=fruit.jpg width="100%" height="100%">
|
||||
</BODY>
|
||||
</HTML>
|
||||
11
dom/html/test/body-margin-test/test-frame.html
Normal file
11
dom/html/test/body-margin-test/test-frame.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>iframe now showing margin/padding in pale moon</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#000099" TEXT="#000000" TOPMARGIN=0 BOTTOMMARGIN=0 LEFTMARGIN=0 RIGHTMARGIN=0 MARGINWIDTH=0 MARGINHEIGHT=0>
|
||||
|
||||
<IFRAME SRC=child.html MARGINWIDTH=0 MARGINHEIGHT=0 HSPACE=0 VSPACE=0 FRAMEBORDER=0 SCROLLING=NO WIDTH=800 HEIGHT=600>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
@ -465,10 +465,12 @@ MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
|
|||
}
|
||||
RefPtr<SamplesHolder> samples = new SamplesHolder;
|
||||
samples->mSamples.AppendElement(sample);
|
||||
if (mNextRandomAccessPoint.ToMicroseconds() <= sample->mTime) {
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mNextRandomAccessPoint =
|
||||
mManager->GetNextRandomAccessPoint(mType, MediaSourceDemuxer::EOS_FUZZ);
|
||||
if (mNextRandomAccessPoint.ToMicroseconds() <= sample->mTime) {
|
||||
mNextRandomAccessPoint =
|
||||
mManager->GetNextRandomAccessPoint(mType, MediaSourceDemuxer::EOS_FUZZ);
|
||||
}
|
||||
}
|
||||
return SamplesPromise::CreateAndResolve(samples, __func__);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -611,7 +611,8 @@ WAVTrackDemuxer::Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize)
|
|||
{
|
||||
const int64_t streamLen = StreamLength();
|
||||
if (mInfo && streamLen > 0) {
|
||||
aSize = std::min<int64_t>(aSize, streamLen - aOffset);
|
||||
int64_t max = streamLen > aOffset ? streamLen - aOffset : 0;
|
||||
aSize = std::min<int64_t>(aSize, max);
|
||||
}
|
||||
uint32_t read = 0;
|
||||
const nsresult rv = mSource.ReadAt(aOffset,
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ void WebMBufferedState::NotifyDataArrived(const unsigned char* aBuffer, uint32_t
|
|||
}
|
||||
|
||||
void WebMBufferedState::Reset() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mRangeParsers.Clear();
|
||||
mTimeMapping.Clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -730,12 +730,17 @@ PromiseWorkerProxy::Create(WorkerPrivate* aWorkerPrivate,
|
|||
RefPtr<PromiseWorkerProxy> proxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise, aCb);
|
||||
|
||||
// Maintain a reference so that we have a valid object to clean up when
|
||||
// removing the feature.
|
||||
proxy.get()->AddRef();
|
||||
|
||||
// We do this to make sure the worker thread won't shut down before the
|
||||
// promise is resolved/rejected on the worker thread.
|
||||
if (!proxy->AddRefObject()) {
|
||||
// Probably the worker is terminating. We cannot complete the operation
|
||||
// and we have to release all the resources.
|
||||
proxy->CleanProperties();
|
||||
// and we have to release all the resources. CleanUp releases the extra
|
||||
// ref, too
|
||||
proxy->CleanUp();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -763,24 +768,6 @@ PromiseWorkerProxy::~PromiseWorkerProxy()
|
|||
MOZ_ASSERT(!mWorkerPrivate);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseWorkerProxy::CleanProperties()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
worker->AssertIsOnWorkerThread();
|
||||
#endif
|
||||
// Ok to do this unprotected from Create().
|
||||
// CleanUp() holds the lock before calling this.
|
||||
mCleanedUp = true;
|
||||
mWorkerPromise = nullptr;
|
||||
mWorkerPrivate = nullptr;
|
||||
|
||||
// Clear the StructuredCloneHolderBase class.
|
||||
Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
PromiseWorkerProxy::AddRefObject()
|
||||
{
|
||||
|
|
@ -881,8 +868,9 @@ PromiseWorkerProxy::CleanUp()
|
|||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
// Release the Promise and remove the PromiseWorkerProxy from the holders of
|
||||
// the worker thread since the Promise has been resolved/rejected or the
|
||||
|
|
@ -890,7 +878,12 @@ PromiseWorkerProxy::CleanUp()
|
|||
MOZ_ASSERT(mWorkerHolder);
|
||||
mWorkerHolder = nullptr;
|
||||
|
||||
CleanProperties();
|
||||
mCleanedUp = true;
|
||||
mWorkerPromise = nullptr;
|
||||
mWorkerPrivate = nullptr;
|
||||
|
||||
// Clear the StructuredCloneHolderBase class.
|
||||
Clear();
|
||||
}
|
||||
Release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,9 +190,6 @@ private:
|
|||
|
||||
bool AddRefObject();
|
||||
|
||||
// If not called from Create(), be sure to hold Lock().
|
||||
void CleanProperties();
|
||||
|
||||
// Function pointer for calling Promise::{ResolveInternal,RejectInternal}.
|
||||
typedef void (Promise::*RunCallbackFunc)(JSContext*,
|
||||
JS::Handle<JS::Value>);
|
||||
|
|
|
|||
|
|
@ -812,6 +812,10 @@ HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
|
|||
if (!string.init(aCx, aSpecifier)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!aModule || !aCx) {
|
||||
// Our module context was ripped out from under us...
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
|
||||
|
||||
|
|
@ -824,6 +828,10 @@ HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
|
|||
|
||||
ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
|
||||
MOZ_ASSERT(ms, "Resolved module not found in module map");
|
||||
if (!ms) {
|
||||
// Already-resolved module has been removed from the map/unloaded...
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!ms->HasParseError());
|
||||
MOZ_ASSERT(ms->ModuleRecord());
|
||||
|
|
|
|||
|
|
@ -213,8 +213,10 @@ DOMStorageDBChild::RecvObserve(const nsCString& aTopic,
|
|||
const nsString& aOriginAttributesPattern,
|
||||
const nsCString& aOriginScope)
|
||||
{
|
||||
DOMStorageObserver::Self()->Notify(
|
||||
aTopic.get(), aOriginAttributesPattern, aOriginScope);
|
||||
DOMStorageObserver* observer = DOMStorageObserver::Self();
|
||||
if (observer) {
|
||||
observer->Notify(aTopic.get(), aOriginAttributesPattern, aOriginScope);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ DOMStorageObserver::Shutdown()
|
|||
if (!sSelf) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
sSelf->mSinks.Clear();
|
||||
|
||||
NS_RELEASE(sSelf);
|
||||
return NS_OK;
|
||||
|
|
@ -123,6 +125,10 @@ DOMStorageObserver::Observe(nsISupports* aSubject,
|
|||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
if (NS_WARN_IF(!sSelf)) { // Shutdown took place, so bail.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Start the thread that opens the database.
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@
|
|||
* The origin of this IDL file is
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#functiocn
|
||||
*
|
||||
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
||||
* Opera Software ASA. You are granted a license to use, reproduce
|
||||
* and create derivative works of this document.
|
||||
* © Copyright 2004-2022 Apple Computer, Inc., Mozilla Foundation,
|
||||
* Opera Software ASA and Moonchild Productions. You are granted a license to use,
|
||||
* reproduce and create derivative works of this document.
|
||||
*/
|
||||
|
||||
callback Function = any(any... arguments);
|
||||
|
||||
callback VoidFunction = void ();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,12 @@ interface Selection {
|
|||
[Throws]
|
||||
boolean containsNode(Node node, boolean allowPartialContainment);
|
||||
|
||||
[Throws]
|
||||
void setBaseAndExtent(Node anchorNode,
|
||||
unsigned long anchorOffset,
|
||||
Node focusNode,
|
||||
unsigned long focusOffset);
|
||||
|
||||
stringifier;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ interface WindowOrWorkerGlobalScope {
|
|||
long setInterval(DOMString handler, optional long timeout, any... unused);
|
||||
void clearInterval(optional long handle = 0);
|
||||
|
||||
// microtask queuing
|
||||
void queueMicrotask(VoidFunction callback);
|
||||
|
||||
// ImageBitmap
|
||||
[Throws]
|
||||
Promise<ImageBitmap> createImageBitmap(ImageBitmapSource aImage);
|
||||
|
|
|
|||
|
|
@ -2233,6 +2233,10 @@ void ReportLoadError(ErrorResult& aRv, nsresult aLoadResult,
|
|||
aLoadResult = NS_ERROR_DOM_SECURITY_ERR;
|
||||
break;
|
||||
|
||||
case NS_ERROR_CORRUPTED_CONTENT:
|
||||
aLoadResult = NS_ERROR_DOM_NETWORK_ERR;
|
||||
break;
|
||||
|
||||
default:
|
||||
// For lack of anything better, go ahead and throw a NetworkError here.
|
||||
// We don't want to throw a JS exception, because for toplevel script
|
||||
|
|
|
|||
|
|
@ -4646,9 +4646,14 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(mThread);
|
||||
|
||||
RefPtr<WorkerThread> thread;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mJSContext = aCx;
|
||||
// mThread is set before we enter, and is never changed during DoRunLoop.
|
||||
// copy to local so we don't trigger mutex analysis
|
||||
MOZ_ASSERT(mThread);
|
||||
thread = mThread;
|
||||
|
||||
MOZ_ASSERT(mStatus == Pending);
|
||||
mStatus = Running;
|
||||
|
|
@ -4678,7 +4683,7 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
|
||||
while (mControlQueue.IsEmpty() &&
|
||||
!(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty()) &&
|
||||
!(normalRunnablesPending = NS_HasPendingEvents(mThread))) {
|
||||
!(normalRunnablesPending = NS_HasPendingEvents(thread))) {
|
||||
WaitForWorkerEvents();
|
||||
}
|
||||
|
||||
|
|
@ -4688,7 +4693,7 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
// irrelevant
|
||||
|
||||
// The state of the world may have changed, recheck it.
|
||||
normalRunnablesPending = NS_HasPendingEvents(mThread);
|
||||
normalRunnablesPending = NS_HasPendingEvents(thread);
|
||||
// The debugger queue doesn't get cleared, so we can ignore that.
|
||||
}
|
||||
|
||||
|
|
@ -4781,9 +4786,9 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
}
|
||||
} else if (normalRunnablesPending) {
|
||||
// Process a single runnable from the main queue.
|
||||
NS_ProcessNextEvent(mThread, false);
|
||||
NS_ProcessNextEvent(thread, false);
|
||||
|
||||
normalRunnablesPending = NS_HasPendingEvents(mThread);
|
||||
normalRunnablesPending = NS_HasPendingEvents(thread);
|
||||
if (normalRunnablesPending && GlobalScope()) {
|
||||
// Now *might* be a good time to GC. Let the JS engine make the decision.
|
||||
JSAutoCompartment ac(aCx, GlobalScope()->GetGlobalJSObject());
|
||||
|
|
@ -5185,10 +5190,14 @@ WorkerPrivate::ClearMainEventQueue(WorkerRanOrNot aRanOrNot)
|
|||
mCancelAllPendingRunnables = true;
|
||||
|
||||
if (WorkerNeverRan == aRanOrNot) {
|
||||
for (uint32_t count = mPreStartRunnables.Length(), index = 0;
|
||||
index < count;
|
||||
nsTArray<RefPtr<WorkerRunnable>> prestart;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPreStartRunnables.SwapElements(prestart);
|
||||
}
|
||||
for (uint32_t count = prestart.Length(), index = 0; index < count;
|
||||
index++) {
|
||||
RefPtr<WorkerRunnable> runnable = mPreStartRunnables[index].forget();
|
||||
RefPtr<WorkerRunnable> runnable = prestart[index].forget();
|
||||
static_cast<nsIRunnable*>(runnable.get())->Run();
|
||||
}
|
||||
} else {
|
||||
|
|
@ -5434,20 +5443,20 @@ WorkerPrivate::CreateNewSyncLoop(Status aFailStatus)
|
|||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIEventTarget> realEventTarget;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mStatus >= aFailStatus) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
|
||||
MOZ_ASSERT(thread);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(thread->PushEventQueue(getter_AddRefs(realEventTarget)));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
|
||||
MOZ_ASSERT(thread);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> realEventTarget;
|
||||
MOZ_ALWAYS_SUCCEEDS(thread->PushEventQueue(getter_AddRefs(realEventTarget)));
|
||||
|
||||
RefPtr<EventTarget> workerEventTarget =
|
||||
new EventTarget(this, realEventTarget);
|
||||
|
||||
|
|
@ -5469,9 +5478,18 @@ WorkerPrivate::RunCurrentSyncLoop()
|
|||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<WorkerThread> thread;
|
||||
JSContext* cx = GetJSContext();
|
||||
MOZ_ASSERT(cx);
|
||||
|
||||
// mThread is set before we enter, and is never changed during
|
||||
// RunCurrentSyncLoop.
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
// Copy to local
|
||||
thread = mThread;
|
||||
}
|
||||
|
||||
// This should not change between now and the time we finish running this sync
|
||||
// loop.
|
||||
uint32_t currentLoopIndex = mSyncLoopStack.Length() - 1;
|
||||
|
|
@ -5490,7 +5508,7 @@ WorkerPrivate::RunCurrentSyncLoop()
|
|||
bool normalRunnablesPending = false;
|
||||
|
||||
// Don't block with the periodic GC timer running.
|
||||
if (!NS_HasPendingEvents(mThread)) {
|
||||
if (!NS_HasPendingEvents(thread)) {
|
||||
SetGCTimerMode(IdleTimer);
|
||||
}
|
||||
|
||||
|
|
@ -5501,7 +5519,7 @@ WorkerPrivate::RunCurrentSyncLoop()
|
|||
for (;;) {
|
||||
while (mControlQueue.IsEmpty() &&
|
||||
!normalRunnablesPending &&
|
||||
!(normalRunnablesPending = NS_HasPendingEvents(mThread))) {
|
||||
!(normalRunnablesPending = NS_HasPendingEvents(thread))) {
|
||||
WaitForWorkerEvents();
|
||||
}
|
||||
|
||||
|
|
@ -5510,7 +5528,7 @@ WorkerPrivate::RunCurrentSyncLoop()
|
|||
// XXXkhuey how should we handle Abort here? See Bug 1003730.
|
||||
|
||||
// The state of the world may have changed. Recheck it.
|
||||
normalRunnablesPending = NS_HasPendingEvents(mThread);
|
||||
normalRunnablesPending = NS_HasPendingEvents(thread);
|
||||
|
||||
// NB: If we processed a NotifyRunnable, we might have run
|
||||
// non-control runnables, one of which may have shut down the
|
||||
|
|
@ -5533,7 +5551,7 @@ WorkerPrivate::RunCurrentSyncLoop()
|
|||
// Make sure the periodic timer is running before we continue.
|
||||
SetGCTimerMode(PeriodicTimer);
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(mThread, false));
|
||||
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(thread, false));
|
||||
|
||||
// Now *might* be a good time to GC. Let the JS engine make the decision.
|
||||
if (JS::CurrentGlobalOrNull(cx)) {
|
||||
|
|
@ -5542,7 +5560,7 @@ WorkerPrivate::RunCurrentSyncLoop()
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure that the stack didn't change underneath us.
|
||||
// Make sure that the stack didn't change under us.
|
||||
MOZ_ASSERT(mSyncLoopStack[currentLoopIndex] == loopInfo);
|
||||
|
||||
return DestroySyncLoop(currentLoopIndex);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsXBLDocumentInfo.h"
|
||||
#include "mozilla/dom/XBLChildrenElement.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
|
||||
#include "nsIStyleRuleProcessor.h"
|
||||
#include "nsRuleProcessorData.h"
|
||||
|
|
@ -663,13 +664,32 @@ nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
|||
|
||||
NS_ASSERTION(aData->mElement, "How did that happen?");
|
||||
|
||||
// Walk the rules in shadow root for :host pseudo-class rules.
|
||||
aData->mTreeMatchContext.mOnlyMatchHostPseudo = true;
|
||||
aData->mElementIsFeatureless = true;
|
||||
|
||||
ShadowRoot* currentShadow = aData->mElement->GetShadowRoot();
|
||||
|
||||
if (currentShadow) {
|
||||
nsXBLBinding* associatedBinding = currentShadow->GetAssociatedBinding();
|
||||
if (associatedBinding) {
|
||||
aData->mTreeMatchContext.mScopedRoot = aData->mElement;
|
||||
associatedBinding->WalkRules(aFunc, aData);
|
||||
}
|
||||
}
|
||||
|
||||
aData->mElementIsFeatureless = false;
|
||||
aData->mTreeMatchContext.mOnlyMatchHostPseudo = false;
|
||||
|
||||
// Walk the binding scope chain, starting with the binding attached to our
|
||||
// content, up till we run out of scopes or we get cut off.
|
||||
nsIContent *content = aData->mElement;
|
||||
|
||||
do {
|
||||
nsXBLBinding *binding = content->GetXBLBinding();
|
||||
if (binding) {
|
||||
if (binding &&
|
||||
// Unlike XBL, styles in the shadow root are not applied to the host.
|
||||
!(content == aData->mElement && binding->IsShadowRootBinding())) {
|
||||
aData->mTreeMatchContext.mScopedRoot = content;
|
||||
binding->WalkRules(aFunc, aData);
|
||||
// If we're not looking at our original content, allow the binding to cut
|
||||
|
|
@ -702,14 +722,26 @@ nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
|||
typedef nsTHashtable<nsPtrHashKey<nsIStyleRuleProcessor> > RuleProcessorSet;
|
||||
|
||||
static RuleProcessorSet*
|
||||
GetContentSetRuleProcessors(nsTHashtable<nsRefPtrHashKey<nsIContent>>* aContentSet)
|
||||
GetContentSetRuleProcessors(nsTHashtable<nsRefPtrHashKey<nsIContent>>* aContentSet, bool aOnlyWalkShadowRootRules)
|
||||
{
|
||||
RuleProcessorSet* set = nullptr;
|
||||
|
||||
for (auto iter = aContentSet->Iter(); !iter.Done(); iter.Next()) {
|
||||
nsIContent* boundContent = iter.Get()->GetKey();
|
||||
for (nsXBLBinding* binding = boundContent->GetXBLBinding(); binding;
|
||||
binding = binding->GetBaseBinding()) {
|
||||
|
||||
// If we are only walking rules for shadow root hosts, skip other types
|
||||
// of bound content.
|
||||
ShadowRoot *shadowRoot = boundContent->GetShadowRoot();
|
||||
if (aOnlyWalkShadowRootRules && !shadowRoot) {
|
||||
return set;
|
||||
}
|
||||
|
||||
// Bound content may have multiple rule processors, potentially one
|
||||
// for its immediate binding, and one more for each binding in the
|
||||
// inheritance chain. Additionally, a bound content may host multiple
|
||||
// shadow roots, each with its own rule processor.
|
||||
for (nsXBLBinding *binding = boundContent->GetXBLBinding(); binding;
|
||||
binding = binding->GetBaseBinding()) {
|
||||
nsIStyleRuleProcessor* ruleProc =
|
||||
binding->PrototypeBinding()->GetRuleProcessor();
|
||||
if (ruleProc) {
|
||||
|
|
@ -718,22 +750,27 @@ GetContentSetRuleProcessors(nsTHashtable<nsRefPtrHashKey<nsIContent>>* aContentS
|
|||
}
|
||||
set->PutEntry(ruleProc);
|
||||
}
|
||||
|
||||
if (shadowRoot) {
|
||||
binding = shadowRoot->GetAssociatedBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
void
|
||||
nsBindingManager::WalkAllRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
||||
ElementDependentRuleProcessorData* aData)
|
||||
ElementDependentRuleProcessorData* aData,
|
||||
bool aOnlyWalkShadowRootRules)
|
||||
{
|
||||
if (!mBoundContentSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoPtr<RuleProcessorSet> set;
|
||||
set = GetContentSetRuleProcessors(mBoundContentSet);
|
||||
set = GetContentSetRuleProcessors(mBoundContentSet, aOnlyWalkShadowRootRules);
|
||||
if (!set) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -744,6 +781,17 @@ nsBindingManager::WalkAllRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
|||
}
|
||||
}
|
||||
|
||||
// The approach in WalkAllShadowRootHostRules seems reasonable on the surface and reminds me of what is done with mScopedRoot elsewhere. But something important is missing, either here or in the code that would normally use it.
|
||||
|
||||
void
|
||||
nsBindingManager::WalkAllShadowRootHostRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
||||
ElementDependentRuleProcessorData* aData)
|
||||
{
|
||||
aData->mTreeMatchContext.mOnlyMatchHostPseudo = true;
|
||||
WalkAllRules(aFunc, aData, true);
|
||||
aData->mTreeMatchContext.mOnlyMatchHostPseudo = false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBindingManager::MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
bool* aRulesChanged)
|
||||
|
|
@ -754,7 +802,7 @@ nsBindingManager::MediumFeaturesChanged(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
nsAutoPtr<RuleProcessorSet> set;
|
||||
set = GetContentSetRuleProcessors(mBoundContentSet);
|
||||
set = GetContentSetRuleProcessors(mBoundContentSet, false);
|
||||
if (!set) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,11 @@ public:
|
|||
bool* aCutOffInheritance);
|
||||
|
||||
void WalkAllRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
||||
ElementDependentRuleProcessorData* aData);
|
||||
ElementDependentRuleProcessorData* aData,
|
||||
bool aOnlyWalkShadowRootRules = false);
|
||||
|
||||
void WalkAllShadowRootHostRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
||||
ElementDependentRuleProcessorData* aData);
|
||||
/**
|
||||
* Do any processing that needs to happen as a result of a change in
|
||||
* the characteristics of the medium, and return whether this rule
|
||||
|
|
|
|||
|
|
@ -138,6 +138,11 @@ public:
|
|||
|
||||
mozilla::dom::XBLChildrenElement* FindInsertionPointFor(nsIContent* aChild);
|
||||
|
||||
bool IsShadowRootBinding()
|
||||
{
|
||||
return mIsShadowRootBinding;
|
||||
}
|
||||
|
||||
bool HasFilteredInsertionPoints()
|
||||
{
|
||||
return !mInsertionPoints.IsEmpty();
|
||||
|
|
|
|||
|
|
@ -201,8 +201,9 @@ public:
|
|||
}
|
||||
|
||||
size_t
|
||||
SizeOfThis(MallocSizeOf aMallocSizeOf) const
|
||||
SizeOfThis(MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -239,9 +239,10 @@ txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
|
|||
class txVariable : public txIGlobalParameter
|
||||
{
|
||||
public:
|
||||
explicit txVariable(nsIVariant* aValue) : mValue(aValue)
|
||||
explicit txVariable(nsIVariant* aValue, txAExprResult* aTxValue)
|
||||
: mValue(aValue)
|
||||
{
|
||||
NS_ASSERTION(aValue, "missing value");
|
||||
NS_ASSERTION(aValue && aTxValue, "missing value");
|
||||
}
|
||||
explicit txVariable(txAExprResult* aValue) : mTxValue(aValue)
|
||||
{
|
||||
|
|
@ -249,12 +250,13 @@ public:
|
|||
}
|
||||
nsresult getValue(txAExprResult** aValue)
|
||||
{
|
||||
NS_ASSERTION(mValue || mTxValue, "variablevalue is null");
|
||||
|
||||
if (!mTxValue) {
|
||||
nsresult rv = Convert(mValue, getter_AddRefs(mTxValue));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// XXX: This should not happen as we normally convert values before
|
||||
// we call this function. For corner cases where this isn't true, we
|
||||
// perform the conversion here.
|
||||
nsresult rv = Convert(mValue, getter_AddRefs(mTxValue));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
*aValue = mTxValue;
|
||||
NS_ADDREF(*aValue);
|
||||
|
|
@ -271,11 +273,11 @@ public:
|
|||
{
|
||||
return mValue;
|
||||
}
|
||||
void setValue(nsIVariant* aValue)
|
||||
void setValue(nsIVariant* aValue, txAExprResult* aTxValue)
|
||||
{
|
||||
NS_ASSERTION(aValue, "setting variablevalue to null");
|
||||
NS_ASSERTION(aValue && aTxValue, "setting variablevalue to null");
|
||||
mValue = aValue;
|
||||
mTxValue = nullptr;
|
||||
mTxValue = aTxValue;
|
||||
}
|
||||
void setValue(txAExprResult* aValue)
|
||||
{
|
||||
|
|
@ -284,14 +286,14 @@ public:
|
|||
mTxValue = aValue;
|
||||
}
|
||||
|
||||
static nsresult Convert(nsIVariant *aValue, txAExprResult** aResult);
|
||||
|
||||
friend void ImplCycleCollectionUnlink(txVariable& aVariable);
|
||||
friend void ImplCycleCollectionTraverse(
|
||||
nsCycleCollectionTraversalCallback& aCallback, txVariable& aVariable,
|
||||
const char* aName, uint32_t aFlags);
|
||||
|
||||
private:
|
||||
static nsresult Convert(nsIVariant *aValue, txAExprResult** aResult);
|
||||
|
||||
nsCOMPtr<nsIVariant> mValue;
|
||||
RefPtr<txAExprResult> mTxValue;
|
||||
};
|
||||
|
|
@ -948,13 +950,17 @@ txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
|
|||
nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
|
||||
txExpandedName varName(nsId, localName);
|
||||
|
||||
RefPtr<txAExprResult> txValue;
|
||||
rv = txVariable::Convert(value, getter_AddRefs(txValue));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
|
||||
if (var) {
|
||||
var->setValue(value);
|
||||
var->setValue(value, txValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
var = new txVariable(value);
|
||||
var = new txVariable(value, txValue);
|
||||
return mVariables.add(varName, var);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,9 +64,12 @@ static setLcdFilterFunc setLcdFilter;
|
|||
/* This is the max number of FT_face objects we keep open at once
|
||||
*/
|
||||
#define MAX_OPEN_FACES 10
|
||||
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
|
||||
|
||||
/* This is the (arbitrary) maximum font size we allow to be passed to
|
||||
FT_Set_Char_Size.
|
||||
Note: This should be equal to FONT_MAX_SIZE in thebes/gfxFont.h
|
||||
*/
|
||||
#define MAX_FONT_SIZE 1000
|
||||
#define MAX_FONT_SIZE 2000
|
||||
|
||||
/**
|
||||
* SECTION:cairo-ft
|
||||
|
|
|
|||
|
|
@ -107,6 +107,16 @@ _cairo_path_bounder_curve_to (void *closure,
|
|||
static cairo_status_t
|
||||
_cairo_path_bounder_close_path (void *closure)
|
||||
{
|
||||
// XXXMC: This addition of a closure point isn't strictly needed but
|
||||
// if our clipping extents code changes then this might cause problems
|
||||
// if the extra point isn't added (in case of 0-length paths).
|
||||
cairo_path_bounder_t *bounder = closure;
|
||||
|
||||
if (bounder->has_initial_point) {
|
||||
_cairo_path_bounder_add_point (bounder, &bounder->current_point);
|
||||
bounder->has_initial_point = FALSE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@
|
|||
#define cairo_scaled_font_get_font_face _moz_cairo_scaled_font_get_font_face
|
||||
#define cairo_scaled_font_get_font_matrix _moz_cairo_scaled_font_get_font_matrix
|
||||
#define cairo_scaled_font_get_font_options _moz_cairo_scaled_font_get_font_options
|
||||
#define cairo_scaled_font_get_hint_metrics _moz_cairo_scaled_font_get_hint_metrics
|
||||
#define cairo_scaled_font_get_reference_count _moz_cairo_scaled_font_get_reference_count
|
||||
#define cairo_scaled_font_get_scale_matrix _moz_cairo_scaled_font_get_scale_matrix
|
||||
#define cairo_scaled_font_get_type _moz_cairo_scaled_font_get_type
|
||||
|
|
|
|||
|
|
@ -2952,3 +2952,23 @@ cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
|
|||
_cairo_font_options_init_copy (options, &scaled_font->options);
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_get_font_options);
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_get_hint_metrics:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Mozilla extension since the required malloc/free to use
|
||||
* cairo_scaled_font_get_font_options() above is too slow.
|
||||
**/
|
||||
cairo_public cairo_hint_metrics_t
|
||||
cairo_scaled_font_get_hint_metrics (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_font_options_t options;
|
||||
if (scaled_font->status) {
|
||||
_cairo_font_options_init_default (&options);
|
||||
} else {
|
||||
_cairo_font_options_init_copy (&options, &scaled_font->options);
|
||||
}
|
||||
return options.hint_metrics;
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_get_hint_metrics);
|
||||
|
|
@ -1265,6 +1265,9 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface,
|
|||
}
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
|
||||
/* Win32 does not support more than 16 elements in the dash array. */
|
||||
if (style->num_dashes > 16)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
/* Win32 does not support a dash offset. */
|
||||
if (style->num_dashes > 0 && style->dash_offset != 0.0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ _cairo_win32_print_gdi_error (const char *context)
|
|||
0, NULL)) {
|
||||
fprintf (stderr, "%s: Unknown GDI error", context);
|
||||
} else {
|
||||
fwprintf (stderr, L"%s: %S", context, (wchar_t *)lpMsgBuf);
|
||||
fprintf (stderr, L"%s: %S", context, (wchar_t *)lpMsgBuf);
|
||||
|
||||
LocalFree (lpMsgBuf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1465,6 +1465,9 @@ cairo_public void
|
|||
cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
// API extension for GRE.
|
||||
cairo_public cairo_hint_metrics_t
|
||||
cairo_scaled_font_get_hint_metrics (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
/* Toy fonts */
|
||||
|
||||
|
|
|
|||
|
|
@ -2434,6 +2434,7 @@ slim_hidden_proto (cairo_scaled_font_get_ctm);
|
|||
slim_hidden_proto (cairo_scaled_font_get_font_face);
|
||||
slim_hidden_proto (cairo_scaled_font_get_font_matrix);
|
||||
slim_hidden_proto (cairo_scaled_font_get_font_options);
|
||||
slim_hidden_proto (cairo_scaled_font_get_hint_metrics); // GRE API extension
|
||||
slim_hidden_proto (cairo_scaled_font_glyph_extents);
|
||||
slim_hidden_proto_no_warn (cairo_scaled_font_reference);
|
||||
slim_hidden_proto (cairo_scaled_font_status);
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# The ARM asm functions here don't appreciate being called by functions
|
||||
# compiled with -mapcs-frame. See bug 832752.
|
||||
CXXFLAGS := $(filter-out -mapcs-frame,$(CXXFLAGS))
|
||||
CFLAGS := $(filter-out -mapcs-frame,$(CFLAGS))
|
||||
77
gfx/cairo/libpixman/src/dither/blue-noise-64x64.h
Normal file
77
gfx/cairo/libpixman/src/dither/blue-noise-64x64.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* WARNING: This file is generated by make-blue-noise.c
|
||||
* Please edit that file instead of this one.
|
||||
*/
|
||||
|
||||
#ifndef BLUE_NOISE_64X64_H
|
||||
#define BLUE_NOISE_64X64_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint16_t dither_blue_noise_64x64[4096] = {
|
||||
3039, 1368, 3169, 103, 2211, 1248, 2981, 668, 2633, 37, 3963, 2903, 384, 2564, 3115, 1973, 3348, 830, 2505, 1293, 3054, 1060, 1505, 3268, 400, 1341, 593, 3802, 3384, 429, 4082, 1411, 2503, 3863, 126, 1292, 1887, 2855, 205, 2094, 2977, 1899, 3924, 356, 3088, 2500, 3942, 1409, 2293, 1734, 3732, 1291, 3227, 277, 2054, 786, 2871, 411, 2425, 1678, 3986, 455, 2879, 2288,
|
||||
388, 1972, 3851, 778, 2768, 3697, 944, 2123, 1501, 3533, 937, 1713, 1381, 3888, 156, 1242, 516, 2888, 1607, 3676, 632, 2397, 3804, 2673, 1898, 3534, 2593, 1777, 1170, 2299, 3013, 1838, 523, 3053, 1647, 3601, 3197, 959, 1520, 3633, 893, 2437, 3367, 2187, 1258, 137, 1965, 401, 3546, 643, 3087, 2498, 733, 2786, 3371, 4053, 1266, 1977, 3663, 183, 2570, 2107, 1183, 3708,
|
||||
907, 2473, 1151, 3363, 1527, 1902, 232, 3903, 3060, 496, 2486, 3206, 2165, 861, 2387, 3653, 2101, 3972, 132, 2162, 3437, 1827, 215, 895, 3114, 271, 969, 2932, 197, 1598, 878, 3696, 1140, 2120, 904, 2431, 302, 3846, 2675, 481, 3187, 66, 1440, 650, 3833, 2826, 3435, 901, 2936, 2111, 250, 1875, 3609, 1174, 1747, 162, 2346, 3420, 913, 3172, 1383, 752, 3298, 1735,
|
||||
3540, 2938, 249, 2324, 526, 3099, 2561, 1324, 2347, 1861, 1200, 3702, 257, 3442, 1514, 2999, 992, 1766, 2735, 1163, 478, 2943, 1279, 3635, 2177, 1464, 3672, 2386, 3871, 3340, 2690, 64, 3489, 2811, 3999, 633, 1948, 1243, 2269, 1807, 1143, 2750, 3729, 1790, 2363, 1053, 1537, 2636, 4065, 1076, 1476, 3869, 450, 2200, 2676, 658, 2979, 1548, 544, 1913, 2838, 3911, 116, 2698,
|
||||
517, 1295, 3997, 1739, 3665, 1083, 3509, 599, 3400, 118, 2956, 720, 2689, 1907, 567, 2523, 284, 3397, 711, 3219, 2450, 3985, 1665, 2549, 562, 3011, 1855, 729, 1355, 528, 1908, 2456, 1384, 337, 1540, 2654, 3138, 3513, 703, 4080, 3314, 2047, 855, 3037, 209, 3317, 577, 1828, 17, 2336, 3193, 2748, 962, 3441, 1450, 3246, 1075, 3878, 2615, 3497, 1033, 2310, 1442, 2183,
|
||||
1654, 3254, 2061, 738, 2832, 148, 2030, 1670, 909, 3850, 2109, 1533, 4046, 1085, 3098, 3897, 1378, 2248, 3829, 1495, 1966, 23, 797, 3427, 1124, 4057, 95, 2787, 2190, 3074, 3950, 742, 3194, 1999, 3386, 1113, 16, 1657, 2804, 201, 1543, 383, 2559, 1325, 3604, 2068, 2493, 3771, 1284, 3460, 710, 1716, 2447, 80, 3811, 2032, 347, 2227, 15, 1689, 397, 3084, 662, 3798,
|
||||
973, 43, 2608, 3143, 1459, 2423, 4066, 2770, 3191, 1283, 2630, 314, 3235, 2289, 72, 1822, 2840, 924, 350, 2653, 1057, 3715, 2235, 2775, 346, 2083, 1553, 3292, 1081, 274, 1686, 1188, 2327, 3743, 578, 2234, 3916, 2519, 1011, 3056, 2207, 3438, 3890, 537, 1617, 837, 3094, 373, 2795, 1980, 276, 3951, 1353, 3015, 844, 1724, 3651, 2923, 1316, 4092, 2504, 3627, 1936, 2854,
|
||||
2461, 3929, 1193, 421, 3746, 820, 1180, 286, 2261, 532, 3625, 1812, 802, 1327, 3527, 670, 3730, 2025, 3124, 3565, 529, 2960, 1769, 1390, 3196, 2494, 3756, 796, 3618, 2602, 3463, 2847, 166, 953, 1745, 2900, 438, 2070, 1418, 3741, 639, 1205, 1891, 2882, 2282, 4012, 1182, 1696, 3630, 951, 2904, 2170, 3530, 375, 2320, 2742, 1132, 701, 3216, 2023, 847, 1230, 310, 3431,
|
||||
770, 1961, 3531, 1702, 2181, 3370, 1877, 3072, 1571, 3389, 1071, 2415, 3782, 2803, 1610, 2454, 1211, 182, 1655, 2322, 1282, 3372, 287, 3935, 704, 1232, 415, 1910, 2286, 1399, 556, 1964, 4068, 2444, 3605, 1272, 3345, 816, 3526, 256, 2402, 2777, 955, 345, 3289, 111, 2727, 635, 2396, 1488, 3331, 600, 1032, 1575, 4026, 515, 3507, 2433, 1605, 460, 3364, 2783, 1810, 1397,
|
||||
2334, 223, 2945, 688, 2533, 99, 2705, 624, 3944, 2073, 46, 2978, 508, 2132, 269, 3173, 3453, 2631, 4076, 694, 1892, 2586, 972, 2178, 3470, 1695, 2849, 3141, 77, 3884, 994, 3029, 1536, 673, 3083, 124, 2583, 1722, 2821, 1944, 4027, 1661, 3176, 3728, 1337, 1813, 3503, 2035, 3930, 157, 2537, 1865, 3096, 2646, 1941, 3252, 1449, 135, 2836, 3758, 2139, 84, 3678, 3106,
|
||||
3862, 1545, 3307, 1320, 3955, 1031, 3664, 1306, 2460, 776, 1487, 3294, 1187, 3990, 1903, 1021, 549, 1484, 943, 3027, 97, 3853, 1499, 2880, 198, 2575, 3995, 1089, 1587, 2475, 3282, 339, 2657, 1158, 2105, 1493, 3943, 580, 3232, 1287, 846, 48, 2480, 2112, 771, 2534, 459, 3134, 850, 1298, 3790, 325, 3652, 1249, 193, 940, 2202, 3895, 1829, 911, 1366, 2577, 1069, 534,
|
||||
2104, 1009, 2667, 392, 1983, 2917, 1645, 324, 3439, 2869, 3705, 1767, 2592, 756, 2916, 3683, 2276, 2850, 2053, 3594, 2403, 3181, 634, 3699, 1933, 906, 519, 2150, 3673, 764, 1770, 2220, 3795, 3336, 502, 3547, 2339, 1110, 301, 2210, 3354, 3643, 569, 1518, 2940, 3973, 1138, 1613, 2773, 2127, 2983, 1671, 769, 2161, 3800, 2730, 3127, 1179, 533, 3259, 2284, 4014, 1651, 2820,
|
||||
3566, 653, 1839, 3455, 2399, 789, 3149, 2244, 1863, 1099, 474, 2307, 158, 3541, 1312, 1711, 0, 3902, 360, 1629, 1091, 395, 1781, 1191, 2374, 3353, 1419, 3225, 206, 2931, 3553, 1046, 54, 1646, 2470, 910, 1860, 3137, 3770, 2635, 1562, 2809, 1215, 3788, 222, 2199, 3335, 67, 3606, 524, 1001, 3309, 2410, 3473, 591, 1619, 291, 2502, 3629, 2891, 335, 741, 3378, 168,
|
||||
2384, 3129, 4051, 22, 1444, 3613, 543, 3893, 186, 2665, 4062, 933, 3058, 2142, 449, 2711, 3224, 849, 1330, 3349, 2195, 2670, 3484, 2993, 32, 3774, 2722, 1859, 2548, 1268, 583, 2027, 3165, 2807, 4029, 227, 2897, 1434, 721, 1816, 195, 905, 2066, 3258, 1754, 970, 2674, 1880, 2338, 3915, 1485, 2660, 14, 1313, 2914, 2046, 4074, 791, 1917, 1301, 1725, 2687, 2019, 1443,
|
||||
418, 1186, 1664, 2859, 1049, 2056, 2741, 1226, 1589, 3186, 2042, 1377, 3449, 1574, 3941, 1063, 1930, 2501, 3751, 2930, 671, 4031, 888, 2081, 1544, 684, 1117, 351, 4052, 1698, 2393, 3881, 1439, 785, 1277, 2013, 3488, 441, 2459, 3980, 3061, 3481, 2543, 419, 3020, 609, 3515, 1350, 799, 2878, 348, 2034, 3966, 1824, 950, 3281, 1394, 2239, 3452, 55, 3922, 3119, 892, 3785,
|
||||
3023, 2140, 782, 2492, 3817, 241, 3355, 2424, 856, 3639, 612, 2556, 245, 2858, 705, 2316, 3562, 495, 1748, 128, 1912, 1454, 280, 2552, 3905, 3130, 2274, 3472, 834, 3055, 240, 2692, 471, 2272, 3301, 2632, 1080, 3693, 2136, 1029, 1364, 590, 1611, 4067, 1190, 2360, 3827, 261, 3180, 1768, 3471, 1103, 3003, 520, 3674, 151, 2571, 555, 3033, 982, 2353, 504, 1259, 2555,
|
||||
149, 3889, 3380, 493, 3178, 1681, 663, 1924, 2990, 49, 1792, 3861, 1192, 1987, 3273, 297, 1457, 3043, 1177, 2292, 3249, 2829, 3682, 1154, 1758, 428, 2872, 1993, 1500, 3703, 1129, 3421, 1840, 3754, 163, 659, 1733, 3182, 38, 2875, 1957, 3614, 2237, 78, 1873, 2801, 1513, 2121, 1074, 2516, 667, 3710, 1429, 2430, 2088, 2830, 1072, 3557, 1531, 2733, 1955, 3286, 3590, 1826,
|
||||
2778, 1068, 1932, 1452, 2279, 1185, 3564, 3952, 1391, 2726, 3313, 2331, 870, 3709, 1674, 2772, 4085, 808, 2596, 3848, 927, 538, 2335, 3334, 773, 3597, 1347, 109, 2663, 608, 2108, 2994, 936, 1524, 2922, 3968, 2422, 1467, 845, 3870, 321, 2704, 1073, 3308, 3680, 823, 430, 3375, 4030, 112, 2171, 2695, 267, 3374, 731, 1627, 3919, 1871, 352, 3839, 1370, 234, 794, 1532,
|
||||
3245, 647, 3575, 74, 3045, 2766, 285, 2174, 498, 1059, 1551, 385, 3125, 2598, 143, 1128, 2095, 3395, 318, 1590, 3524, 1345, 1969, 242, 2759, 2092, 947, 3926, 3244, 2356, 1658, 6, 3593, 2554, 1172, 1995, 371, 2755, 3417, 2294, 1570, 3164, 748, 2517, 1401, 3111, 2420, 1662, 2910, 1276, 3276, 854, 1804, 4000, 1253, 2987, 229, 2344, 3184, 649, 2196, 2921, 4095, 2389,
|
||||
1289, 2193, 2579, 4023, 757, 1858, 986, 3199, 2514, 3475, 4021, 2154, 651, 1432, 3468, 2404, 574, 1799, 3105, 2145, 86, 2614, 3218, 1565, 4088, 2481, 3079, 1815, 323, 1212, 3837, 759, 2159, 435, 3223, 784, 3659, 1114, 1888, 550, 1221, 3786, 1803, 499, 2117, 185, 3763, 942, 589, 2001, 3838, 1483, 3154, 2256, 468, 2544, 3403, 898, 1208, 2610, 3622, 967, 1929, 378,
|
||||
3781, 220, 1656, 1115, 3347, 2428, 3822, 1577, 712, 1959, 110, 2765, 1762, 3854, 979, 2928, 3714, 1371, 746, 3969, 2884, 975, 3779, 641, 1142, 159, 1460, 702, 3485, 2866, 2495, 3330, 1305, 3937, 1635, 2229, 2962, 146, 4055, 3091, 2417, 100, 3508, 2933, 4006, 1167, 1920, 2760, 3552, 2545, 433, 2845, 142, 1056, 1886, 3616, 1435, 2099, 3803, 1749, 27, 1446, 3350, 2843,
|
||||
884, 3310, 2948, 2103, 447, 1351, 187, 2895, 3655, 1256, 3036, 932, 3325, 2257, 451, 1915, 40, 2780, 2438, 1112, 1814, 423, 2290, 1905, 2898, 3419, 2306, 3760, 1938, 486, 1019, 1791, 3010, 2628, 203, 3408, 1269, 2507, 1606, 862, 2779, 2078, 952, 1529, 2638, 708, 3332, 1413, 2, 1726, 1156, 3500, 2392, 3791, 3076, 812, 107, 2861, 501, 3050, 3487, 2455, 594, 1731,
|
||||
2685, 1498, 680, 3908, 2621, 3529, 1786, 2236, 342, 2569, 1526, 3722, 230, 1290, 3203, 3947, 1609, 3516, 467, 3267, 3685, 1461, 3140, 3569, 367, 1759, 928, 2754, 1332, 2219, 4034, 260, 655, 1984, 978, 3814, 617, 2086, 3525, 279, 3841, 1373, 3361, 319, 2251, 3066, 407, 2382, 3918, 3133, 2168, 762, 1523, 507, 2641, 1677, 4025, 2413, 1584, 793, 2049, 1109, 3962, 2218,
|
||||
1194, 3692, 266, 1687, 981, 3103, 740, 3983, 1005, 3434, 570, 2383, 1942, 2718, 676, 2462, 1007, 2089, 1308, 2222, 233, 2568, 829, 1241, 2669, 3987, 514, 3303, 69, 3142, 1603, 3560, 2295, 3288, 1497, 2696, 1764, 2865, 1058, 3271, 1914, 477, 2529, 3927, 1736, 1273, 3752, 2029, 1012, 565, 2798, 4078, 1949, 3305, 1175, 2179, 380, 3366, 1195, 3849, 2637, 416, 2959, 125,
|
||||
3396, 2467, 2036, 3234, 2340, 68, 2819, 1436, 2011, 3139, 1704, 4073, 860, 3582, 1468, 2969, 211, 3157, 4056, 866, 2935, 2000, 3923, 31, 2157, 1477, 2429, 1147, 3792, 2557, 774, 2802, 1153, 3747, 464, 3192, 42, 3904, 539, 1474, 2283, 803, 2876, 1061, 75, 3477, 747, 2893, 1538, 3626, 251, 1322, 2506, 189, 2791, 3667, 939, 2991, 1971, 175, 3195, 1416, 3648, 1857,
|
||||
3052, 454, 851, 3789, 1271, 1906, 3694, 2484, 406, 2757, 26, 1189, 2909, 296, 2215, 3784, 1864, 637, 2715, 1673, 3445, 581, 1572, 3059, 3469, 761, 2984, 1737, 2058, 440, 1414, 1921, 121, 2527, 894, 2223, 1302, 2377, 3077, 2666, 3759, 3198, 1811, 3661, 2166, 2731, 1883, 359, 3285, 2458, 1805, 3459, 926, 3834, 675, 1893, 1496, 2612, 657, 3523, 1763, 2354, 564, 961,
|
||||
1367, 3977, 1588, 2714, 322, 3446, 1088, 625, 3887, 1354, 3535, 2090, 3316, 1760, 1127, 483, 3491, 1421, 2301, 94, 1202, 3740, 2311, 1014, 1878, 3836, 180, 3412, 991, 2868, 3953, 3450, 3081, 1632, 4071, 1882, 3543, 726, 1719, 179, 1171, 364, 1420, 622, 3090, 1490, 946, 4007, 2212, 1102, 619, 2739, 2189, 1669, 2937, 3426, 39, 3940, 2191, 1264, 887, 4091, 2792, 2135,
|
||||
4, 2883, 2281, 631, 3044, 1641, 2232, 3243, 1773, 2319, 827, 2591, 629, 3938, 2426, 3222, 2629, 1044, 3879, 3293, 1952, 2749, 275, 2590, 472, 1372, 2496, 660, 3669, 2264, 208, 915, 2167, 561, 2828, 307, 3265, 1104, 3964, 2155, 3425, 1951, 4077, 2391, 283, 3387, 2581, 115, 1415, 3069, 3896, 141, 3158, 1214, 442, 2405, 1349, 3085, 425, 2528, 3002, 312, 1602, 3588,
|
||||
1137, 3323, 1963, 1002, 3578, 2521, 127, 925, 2970, 273, 3737, 1573, 167, 2863, 1509, 800, 147, 2059, 2942, 409, 921, 3151, 1451, 3909, 3333, 2844, 2096, 1512, 3136, 1210, 1798, 2709, 1331, 3586, 1034, 1521, 2441, 2926, 488, 2585, 775, 3031, 2693, 879, 3602, 1173, 2028, 3654, 2781, 841, 1975, 1507, 3646, 768, 3991, 2012, 996, 3544, 1666, 3810, 1990, 3360, 753, 2597,
|
||||
3736, 304, 1473, 3828, 485, 1334, 4008, 2072, 3495, 1136, 2806, 2004, 3236, 1010, 2130, 3819, 1750, 3567, 644, 2515, 1794, 3636, 698, 2137, 1162, 832, 3761, 326, 2613, 513, 3302, 3820, 357, 3163, 2259, 3733, 101, 1922, 1386, 3587, 1640, 28, 1286, 2141, 1761, 2918, 693, 1639, 457, 3250, 2434, 365, 2599, 1729, 3284, 2643, 306, 2793, 689, 1090, 104, 1309, 2305, 1831,
|
||||
2776, 859, 2446, 2915, 1778, 3337, 2677, 614, 1508, 2409, 469, 4033, 1321, 3563, 402, 3131, 2720, 1093, 1569, 4042, 1229, 2277, 216, 3046, 1817, 57, 3006, 1684, 4059, 2016, 795, 2440, 1652, 1960, 610, 2763, 920, 3864, 3110, 1026, 2326, 3762, 3233, 521, 3856, 173, 2457, 3939, 2138, 1262, 3572, 989, 3021, 2238, 119, 1445, 3832, 1809, 2297, 3467, 2700, 3684, 3102, 394,
|
||||
4036, 2050, 3256, 89, 2198, 1079, 248, 1845, 3805, 3104, 880, 1779, 2688, 717, 2373, 1375, 262, 2249, 3071, 13, 2813, 3429, 1600, 3984, 2416, 3603, 1299, 2298, 998, 3492, 1393, 2951, 10, 4009, 1247, 3462, 1679, 2204, 414, 2736, 316, 1894, 2816, 1050, 3373, 1462, 3107, 817, 3464, 21, 1835, 4070, 568, 1178, 3718, 875, 3168, 466, 2974, 1458, 2084, 616, 1564, 1018,
|
||||
1693, 546, 1244, 3899, 716, 3160, 3608, 2877, 1220, 334, 3443, 2270, 44, 3000, 1843, 3928, 3405, 766, 3686, 2040, 587, 993, 2647, 387, 930, 2753, 630, 3274, 150, 2808, 453, 3638, 1092, 2352, 3030, 239, 2562, 700, 3240, 1257, 4016, 730, 1515, 2203, 2551, 417, 1866, 1123, 2348, 2902, 1550, 2678, 2075, 3238, 1630, 2531, 2115, 1255, 4054, 840, 290, 3874, 2477, 3399,
|
||||
2250, 3577, 2817, 1626, 2576, 1356, 2315, 792, 2087, 2618, 1612, 3855, 1263, 3637, 1036, 494, 1535, 2553, 1198, 1715, 3867, 3170, 1359, 1954, 3483, 1539, 2069, 3886, 1772, 2487, 1534, 2045, 3242, 806, 1578, 2018, 3948, 1423, 3596, 2076, 2466, 3424, 139, 3688, 871, 4049, 2852, 3342, 547, 3719, 327, 852, 3505, 207, 2794, 542, 3600, 45, 2411, 3324, 1788, 3012, 1235, 61,
|
||||
2655, 917, 253, 1986, 3738, 313, 1706, 4072, 120, 3229, 957, 597, 2024, 3262, 2453, 2857, 2002, 3190, 210, 2784, 2206, 300, 2400, 3766, 553, 3152, 218, 1150, 2988, 883, 3753, 627, 2664, 3831, 437, 3385, 1008, 2957, 60, 1636, 891, 2899, 1776, 3062, 1315, 2026, 194, 1643, 2079, 1296, 3201, 2465, 1379, 1927, 3898, 1125, 1847, 2846, 1552, 1028, 2725, 2169, 787, 3202,
|
||||
1441, 3982, 3032, 1052, 3251, 605, 2639, 3073, 1431, 3642, 2329, 2949, 341, 1634, 833, 129, 4020, 916, 3571, 669, 1506, 3411, 821, 2856, 1207, 2337, 2683, 3448, 340, 2214, 3128, 235, 1738, 1288, 2833, 2419, 606, 1884, 2668, 552, 3765, 1176, 399, 2302, 596, 3591, 2634, 767, 3845, 2767, 995, 3967, 491, 3057, 814, 2300, 3422, 691, 3797, 254, 3645, 509, 3478, 1836,
|
||||
2119, 475, 2445, 1525, 2175, 3539, 914, 1926, 473, 1157, 1800, 3971, 2701, 3739, 2129, 3486, 1333, 1784, 2366, 2982, 1070, 4089, 1802, 73, 1642, 3958, 835, 1837, 1480, 4043, 1217, 2469, 3416, 2113, 88, 3668, 1240, 3255, 3920, 2355, 3167, 2003, 2645, 3936, 3228, 1592, 1144, 3474, 2394, 79, 1820, 2241, 1594, 3656, 2584, 153, 1448, 3034, 2005, 2511, 1692, 1335, 3913, 217,
|
||||
2822, 3391, 745, 3813, 192, 1274, 2941, 3847, 2489, 3440, 744, 161, 1422, 1086, 572, 3004, 2617, 338, 3807, 2031, 236, 2472, 3065, 2098, 3358, 362, 2163, 3574, 497, 2788, 1970, 948, 3885, 685, 3100, 1712, 2228, 292, 1408, 1016, 164, 3537, 1417, 941, 34, 2172, 3001, 358, 1491, 3147, 699, 3356, 258, 1149, 2946, 1787, 3931, 382, 1146, 3291, 818, 2890, 2379, 1096,
|
||||
3679, 1328, 1901, 3162, 2747, 1730, 2253, 5, 1556, 2818, 2093, 3166, 2522, 3410, 2287, 1701, 956, 3237, 620, 1596, 3300, 1307, 511, 3701, 1020, 2939, 1362, 2532, 3208, 749, 3641, 160, 1522, 2624, 1095, 4086, 826, 2841, 3583, 2173, 1727, 723, 2925, 1911, 2482, 3726, 863, 1962, 4028, 1111, 2835, 3773, 2449, 2022, 582, 3278, 923, 2619, 2152, 4039, 92, 1934, 3145, 677,
|
||||
2530, 53, 2303, 1003, 458, 3989, 739, 3321, 1064, 369, 3556, 877, 1900, 426, 3876, 1, 3617, 2106, 1197, 2805, 3634, 857, 2706, 1504, 2418, 682, 3868, 20, 1139, 1688, 2333, 3311, 2907, 1945, 265, 2385, 3433, 1601, 636, 2620, 3095, 4044, 386, 3382, 1184, 527, 2814, 3414, 2342, 465, 1889, 1343, 874, 3479, 1502, 2233, 3689, 1385, 559, 2745, 1463, 3465, 376, 1718,
|
||||
3217, 4045, 1580, 3612, 2525, 1228, 3018, 1958, 3725, 2358, 1361, 3996, 1581, 3063, 1224, 2737, 1475, 2442, 3946, 191, 1796, 2128, 3975, 134, 1916, 3318, 1597, 2071, 3749, 2672, 403, 1278, 602, 3745, 3220, 1374, 445, 2064, 3830, 243, 1252, 2390, 1563, 2724, 3875, 1818, 1346, 165, 1650, 3264, 2680, 117, 2998, 4081, 343, 2799, 9, 3122, 1743, 3724, 1040, 2231, 3842, 1209,
|
||||
900, 398, 2851, 697, 1797, 3482, 293, 2679, 1649, 566, 2954, 91, 2697, 714, 2060, 3211, 781, 480, 3040, 1038, 2611, 666, 2989, 3458, 1201, 2796, 548, 2975, 839, 3121, 1850, 4001, 2208, 1631, 790, 2558, 2972, 1148, 3213, 1849, 3624, 971, 2102, 108, 772, 3101, 2589, 3777, 1042, 656, 3907, 2097, 1615, 2540, 805, 1935, 1231, 3494, 2451, 268, 2995, 750, 2682, 2020,
|
||||
3024, 1392, 2124, 3279, 106, 2217, 1387, 822, 3214, 3825, 2160, 1000, 2395, 3691, 228, 4038, 1872, 3413, 1608, 2225, 3536, 303, 1653, 886, 2541, 224, 4037, 2252, 1428, 172, 3504, 958, 2848, 113, 3628, 1834, 3979, 19, 2317, 779, 2797, 518, 3174, 3549, 1482, 2266, 444, 2014, 3555, 2439, 1213, 3113, 535, 1135, 3204, 3858, 2309, 931, 623, 2009, 3359, 1566, 140, 3550,
|
||||
1808, 3872, 2488, 1152, 3764, 2892, 3960, 2412, 353, 1223, 1825, 3444, 3116, 1717, 1082, 2313, 1280, 2661, 82, 3852, 1389, 3200, 2330, 3812, 2038, 3581, 1728, 1039, 3339, 2427, 586, 2580, 1238, 3328, 2280, 1047, 595, 2662, 1363, 3338, 1620, 3934, 2497, 1881, 1054, 3954, 3215, 864, 2887, 1801, 320, 3519, 2378, 3704, 1753, 424, 2958, 1660, 4005, 2601, 1116, 3912, 2381, 573,
|
||||
2740, 200, 828, 1667, 432, 1931, 1035, 1616, 3598, 2640, 728, 264, 1437, 557, 3501, 2966, 372, 3734, 974, 1978, 758, 2719, 1145, 452, 1433, 725, 2681, 408, 3843, 1918, 1547, 3906, 1996, 503, 1456, 3019, 3493, 1700, 3742, 355, 2134, 176, 1311, 615, 2867, 315, 1680, 1314, 8, 3297, 1494, 783, 1950, 83, 2656, 1382, 3561, 138, 2834, 1404, 330, 1904, 3156, 1027,
|
||||
1357, 3381, 3041, 3666, 2729, 734, 3415, 177, 3051, 2021, 4079, 2823, 3775, 2186, 2616, 869, 1668, 3148, 2367, 3315, 393, 4075, 1870, 2920, 3343, 2362, 3188, 1303, 2782, 825, 3171, 259, 2905, 3717, 2538, 184, 2074, 838, 2860, 2407, 1024, 3496, 3008, 3706, 1985, 2349, 3623, 2582, 4058, 2184, 2694, 3873, 2964, 990, 3346, 690, 2033, 1066, 2201, 3490, 2971, 718, 3700, 2188,
|
||||
4061, 391, 1989, 2325, 1430, 3150, 2125, 2526, 592, 1403, 976, 2351, 1165, 1851, 114, 3921, 2063, 613, 1358, 2785, 1623, 2254, 25, 3542, 1045, 246, 1852, 3554, 87, 2243, 3615, 1169, 727, 1705, 968, 3957, 3185, 1251, 500, 4063, 1751, 2622, 842, 1519, 90, 3393, 819, 490, 1874, 999, 571, 1275, 2271, 1586, 4040, 2448, 3126, 3731, 436, 885, 1708, 2421, 24, 1599,
|
||||
889, 2563, 1199, 645, 70, 4013, 1237, 3723, 1694, 3499, 3, 3266, 484, 2997, 3390, 1233, 2842, 3687, 152, 3480, 1084, 3698, 881, 2490, 1542, 3992, 2209, 692, 1690, 3022, 1470, 2625, 2114, 3512, 2359, 381, 2684, 1897, 3368, 1395, 3080, 289, 2065, 3981, 2758, 1141, 3097, 1472, 2870, 3352, 3707, 225, 3159, 505, 1895, 214, 1222, 1774, 2686, 3978, 3275, 1196, 3518, 2825,
|
||||
3270, 1720, 3796, 3466, 2650, 1841, 298, 899, 2862, 2091, 2671, 1744, 3735, 801, 1560, 349, 2262, 903, 1833, 2524, 512, 3117, 1793, 2827, 476, 3038, 1216, 2550, 3826, 980, 431, 4048, 35, 2992, 1265, 1595, 765, 3675, 76, 2247, 696, 3456, 1254, 2452, 664, 1757, 2133, 3750, 145, 2332, 1554, 1981, 3580, 2712, 868, 3640, 2919, 638, 2275, 1427, 309, 2595, 2006, 492,
|
||||
2226, 178, 2911, 836, 1528, 3028, 2240, 3327, 404, 3970, 707, 1294, 2464, 2131, 4032, 2600, 3319, 1406, 2913, 3974, 2156, 1425, 221, 3877, 2017, 811, 3662, 272, 3287, 1988, 2408, 3357, 1746, 598, 3239, 3823, 2182, 2934, 1078, 2604, 3840, 1697, 2906, 413, 3210, 3880, 331, 2644, 1260, 848, 3042, 2535, 1077, 1438, 3261, 2365, 1561, 3799, 85, 3082, 1876, 674, 3932, 1101,
|
||||
3644, 1344, 1943, 2401, 390, 3835, 1048, 2572, 1541, 1133, 3075, 3584, 308, 2889, 1065, 1869, 601, 3783, 282, 1181, 736, 3312, 2368, 1126, 3383, 1675, 2734, 1426, 628, 2873, 1317, 843, 2717, 2048, 1004, 2536, 333, 1782, 3295, 1517, 219, 2153, 815, 3502, 1579, 2268, 987, 3409, 1780, 4018, 354, 665, 3914, 47, 1956, 456, 1006, 2010, 3406, 1130, 3621, 2894, 1549, 3092,
|
||||
2485, 640, 3993, 3179, 1270, 3436, 585, 1925, 3757, 2304, 136, 1976, 1486, 646, 3520, 50, 3155, 1637, 2435, 3522, 1937, 2756, 3748, 661, 2224, 58, 3230, 2357, 1830, 3892, 170, 3607, 1447, 3949, 190, 3392, 1336, 584, 4010, 918, 3016, 3670, 1155, 2406, 52, 1304, 3009, 607, 2085, 2699, 3205, 1848, 2291, 3402, 2764, 3865, 3048, 2508, 735, 2710, 443, 2341, 897, 263,
|
||||
1785, 2769, 983, 56, 2197, 1685, 2703, 202, 2944, 810, 3377, 2626, 3787, 3047, 2055, 1236, 2752, 2122, 945, 3093, 96, 1624, 439, 3014, 1388, 4015, 977, 448, 3506, 1098, 2242, 3026, 506, 2361, 2952, 1862, 3619, 2790, 1992, 2483, 525, 1868, 2652, 4093, 1998, 3595, 2478, 3816, 122, 1412, 929, 3716, 1166, 1648, 813, 1300, 199, 1489, 3998, 1771, 1310, 3808, 2052, 3423,
|
||||
434, 3712, 1625, 3558, 2955, 853, 4019, 1348, 3511, 1732, 1246, 487, 934, 1672, 2510, 3965, 788, 3711, 396, 1369, 4090, 1055, 2603, 1879, 3528, 2518, 2067, 3005, 1516, 2588, 751, 1740, 3418, 1131, 1576, 686, 2296, 1118, 18, 3263, 1365, 3401, 294, 737, 3177, 410, 867, 1633, 2963, 3579, 2375, 252, 2881, 479, 2471, 3576, 2180, 3306, 332, 2255, 3035, 41, 2648, 1396,
|
||||
2929, 2230, 1219, 2512, 446, 2008, 3189, 2388, 626, 2164, 2831, 4047, 2376, 174, 3272, 368, 1469, 3226, 2578, 1991, 2874, 2263, 3681, 876, 188, 1239, 683, 3776, 226, 3183, 4083, 2148, 63, 2649, 3859, 299, 3086, 3933, 1585, 2185, 3767, 988, 1707, 2908, 1407, 1844, 2771, 2245, 1161, 560, 1755, 3376, 2051, 4064, 3135, 1832, 652, 2853, 1051, 3649, 760, 3290, 1105, 3945,
|
||||
872, 154, 3207, 713, 3780, 1453, 281, 1087, 3695, 30, 3299, 1919, 1400, 3551, 1119, 1890, 2314, 618, 1703, 3428, 724, 295, 3146, 1557, 3341, 2896, 1683, 2723, 1974, 1017, 541, 1380, 3720, 804, 3280, 2082, 997, 2567, 777, 2961, 213, 2707, 2328, 3632, 1025, 3891, 3304, 255, 4003, 3108, 2587, 1323, 743, 1479, 105, 1013, 3901, 1618, 2044, 2627, 1465, 1846, 576, 1994,
|
||||
2560, 3521, 1742, 2118, 2800, 3404, 1783, 2609, 2968, 1582, 1022, 412, 2713, 687, 2976, 3857, 2761, 3620, 62, 1108, 3844, 1340, 2100, 540, 2345, 3925, 405, 3457, 1319, 2468, 3362, 2815, 1867, 2372, 1281, 1714, 3690, 482, 3498, 1842, 1285, 3994, 558, 2039, 81, 2499, 678, 1481, 1923, 964, 12, 3824, 2980, 2205, 2762, 3432, 2398, 181, 3247, 462, 4094, 2350, 3589, 3089,
|
||||
1555, 1094, 4041, 247, 1267, 908, 3959, 2041, 732, 3860, 2343, 3132, 3769, 2144, 1621, 237, 912, 1329, 3025, 2146, 2642, 1775, 3721, 2746, 1121, 1953, 902, 2285, 130, 3671, 1659, 278, 3153, 522, 2721, 123, 2996, 1466, 2380, 377, 3231, 873, 1510, 3476, 3123, 1250, 2147, 3650, 2839, 3451, 2323, 1122, 3545, 379, 1765, 1218, 603, 3768, 1360, 938, 2885, 133, 1245, 363,
|
||||
2364, 554, 2743, 3344, 2474, 530, 3112, 169, 1297, 3430, 536, 1741, 98, 1043, 2574, 3253, 2246, 1854, 4022, 510, 3283, 204, 858, 3398, 36, 3118, 1478, 3794, 2986, 706, 2176, 922, 3559, 1097, 3976, 3322, 2149, 1160, 2810, 3883, 2007, 2513, 2953, 328, 1721, 3793, 422, 2566, 807, 329, 1638, 1967, 648, 2520, 3727, 3109, 2116, 2927, 2491, 1939, 3365, 1709, 2728, 3815,
|
||||
2037, 3120, 831, 1405, 1896, 3592, 1622, 2369, 2864, 2151, 1107, 2542, 3532, 1410, 3917, 427, 3568, 709, 2509, 1503, 1037, 2973, 2436, 1604, 4035, 2594, 563, 1819, 2659, 1234, 4004, 2565, 1511, 2273, 1823, 336, 882, 3772, 575, 1628, 171, 3570, 1120, 2260, 2716, 935, 3064, 1806, 1342, 3144, 3900, 2744, 3296, 985, 1546, 238, 896, 1663, 305, 3660, 695, 2213, 960, 3407,
|
||||
144, 1795, 3894, 2267, 51, 2708, 1023, 3818, 366, 1821, 4087, 2985, 755, 2057, 2912, 949, 1583, 2774, 231, 3447, 2258, 3866, 1982, 672, 1225, 2077, 3320, 1062, 370, 3241, 1968, 7, 3068, 681, 3631, 2573, 1567, 3175, 2321, 1067, 3070, 722, 1856, 3744, 642, 1471, 4084, 131, 3514, 2443, 531, 1227, 155, 2265, 4024, 2658, 3326, 3910, 1168, 3078, 1530, 3956, 489, 1424,
|
||||
3647, 1203, 420, 2924, 3755, 719, 3248, 1376, 3067, 890, 196, 1559, 3269, 270, 2432, 1885, 3212, 1164, 3778, 1752, 579, 1338, 344, 3585, 3017, 288, 3658, 2371, 3882, 1691, 611, 2789, 3809, 1339, 389, 2950, 2015, 59, 3548, 2751, 2158, 4011, 1352, 29, 3388, 2370, 2812, 1946, 954, 2110, 1558, 2947, 3573, 1909, 1326, 679, 1853, 2312, 551, 2702, 33, 2414, 3209, 2824,
|
||||
2547, 2143, 3379, 966, 1492, 1979, 2479, 463, 2194, 3657, 2738, 2318, 1261, 3713, 604, 4002, 11, 2192, 2967, 919, 2607, 3369, 2837, 1676, 2539, 984, 1568, 93, 2901, 1318, 3538, 1041, 2216, 1756, 3454, 1030, 4050, 1402, 798, 1723, 311, 3277, 2546, 2886, 2043, 461, 1206, 3677, 361, 3260, 3988, 809, 2605, 470, 3007, 3517, 102, 3221, 1398, 2062, 3611, 1134, 1928, 865,
|
||||
4060, 621, 1710, 2606, 3510, 317, 4017, 1682, 3329, 1159, 1940, 654, 3461, 1789, 1015, 2691, 1455, 3599, 374, 1947, 4069, 71, 2126, 763, 3961, 2278, 3161, 1997, 824, 2623, 2080, 244, 3257, 780, 2732, 2308, 545, 3351, 2476, 3806, 1204, 588, 1591, 963, 3610, 1699, 754, 3049, 2651, 1106, 65, 2221, 1644, 3821, 1100, 2463, 1614, 3801, 965, 2965, 715, 3394, 1593, 212,
|
||||
};
|
||||
|
||||
#endif /* BLUE_NOISE_64X64_H */
|
||||
679
gfx/cairo/libpixman/src/dither/make-blue-noise.c
Normal file
679
gfx/cairo/libpixman/src/dither/make-blue-noise.c
Normal file
|
|
@ -0,0 +1,679 @@
|
|||
/* Blue noise generation using the void-and-cluster method as described in
|
||||
*
|
||||
* The void-and-cluster method for dither array generation
|
||||
* Ulichney, Robert A (1993)
|
||||
*
|
||||
* http://cv.ulichney.com/papers/1993-void-cluster.pdf
|
||||
*
|
||||
* Note that running with openmp (-DUSE_OPENMP) will trigger additional
|
||||
* randomness due to computing reductions in parallel, and is not recommended
|
||||
* unless generating very large dither arrays.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Booleans and utility functions */
|
||||
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
# define FALSE 0
|
||||
#endif
|
||||
|
||||
typedef int bool_t;
|
||||
|
||||
int
|
||||
imin (int x, int y)
|
||||
{
|
||||
return x < y ? x : y;
|
||||
}
|
||||
|
||||
/* Memory allocation */
|
||||
void *
|
||||
malloc_abc (unsigned int a, unsigned int b, unsigned int c)
|
||||
{
|
||||
if (a >= INT32_MAX / b)
|
||||
return NULL;
|
||||
else if (a * b >= INT32_MAX / c)
|
||||
return NULL;
|
||||
else
|
||||
return malloc (a * b * c);
|
||||
}
|
||||
|
||||
/* Random number generation */
|
||||
typedef uint32_t xorwow_state_t[5];
|
||||
|
||||
uint32_t
|
||||
xorwow_next (xorwow_state_t *state)
|
||||
{
|
||||
uint32_t s = (*state)[0],
|
||||
t = (*state)[3];
|
||||
(*state)[3] = (*state)[2];
|
||||
(*state)[2] = (*state)[1];
|
||||
(*state)[1] = s;
|
||||
|
||||
t ^= t >> 2;
|
||||
t ^= t << 1;
|
||||
t ^= s ^ (s << 4);
|
||||
|
||||
(*state)[0] = t;
|
||||
(*state)[4] += 362437;
|
||||
|
||||
return t + (*state)[4];
|
||||
}
|
||||
|
||||
float
|
||||
xorwow_float (xorwow_state_t *s)
|
||||
{
|
||||
return (xorwow_next (s) >> 9) / (float)((1 << 23) - 1);
|
||||
}
|
||||
|
||||
/* Floating point matrices
|
||||
*
|
||||
* Used to cache the cluster sizes.
|
||||
*/
|
||||
typedef struct matrix_t {
|
||||
int width;
|
||||
int height;
|
||||
float *buffer;
|
||||
} matrix_t;
|
||||
|
||||
bool_t
|
||||
matrix_init (matrix_t *matrix, int width, int height)
|
||||
{
|
||||
float *buffer;
|
||||
|
||||
if (!matrix)
|
||||
return FALSE;
|
||||
|
||||
buffer = malloc_abc (width, height, sizeof (float));
|
||||
|
||||
if (!buffer)
|
||||
return FALSE;
|
||||
|
||||
matrix->buffer = buffer;
|
||||
matrix->width = width;
|
||||
matrix->height = height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
matrix_copy (matrix_t *dst, matrix_t const *src)
|
||||
{
|
||||
float *srcbuf = src->buffer,
|
||||
*srcend = src->buffer + src->width * src->height,
|
||||
*dstbuf = dst->buffer;
|
||||
|
||||
if (dst->width != src->width || dst->height != src->height)
|
||||
return FALSE;
|
||||
|
||||
while (srcbuf < srcend)
|
||||
*dstbuf++ = *srcbuf++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
float *
|
||||
matrix_get (matrix_t *matrix, int x, int y)
|
||||
{
|
||||
return &matrix->buffer[y * matrix->width + x];
|
||||
}
|
||||
|
||||
void
|
||||
matrix_destroy (matrix_t *matrix)
|
||||
{
|
||||
free (matrix->buffer);
|
||||
}
|
||||
|
||||
/* Binary patterns */
|
||||
typedef struct pattern_t {
|
||||
int width;
|
||||
int height;
|
||||
bool_t *buffer;
|
||||
} pattern_t;
|
||||
|
||||
bool_t
|
||||
pattern_init (pattern_t *pattern, int width, int height)
|
||||
{
|
||||
bool_t *buffer;
|
||||
|
||||
if (!pattern)
|
||||
return FALSE;
|
||||
|
||||
buffer = malloc_abc (width, height, sizeof (bool_t));
|
||||
|
||||
if (!buffer)
|
||||
return FALSE;
|
||||
|
||||
pattern->buffer = buffer;
|
||||
pattern->width = width;
|
||||
pattern->height = height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
pattern_copy (pattern_t *dst, pattern_t const *src)
|
||||
{
|
||||
bool_t *srcbuf = src->buffer,
|
||||
*srcend = src->buffer + src->width * src->height,
|
||||
*dstbuf = dst->buffer;
|
||||
|
||||
if (dst->width != src->width || dst->height != src->height)
|
||||
return FALSE;
|
||||
|
||||
while (srcbuf < srcend)
|
||||
*dstbuf++ = *srcbuf++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t *
|
||||
pattern_get (pattern_t *pattern, int x, int y)
|
||||
{
|
||||
return &pattern->buffer[y * pattern->width + x];
|
||||
}
|
||||
|
||||
void
|
||||
pattern_fill_white_noise (pattern_t *pattern, float fraction,
|
||||
xorwow_state_t *s)
|
||||
{
|
||||
bool_t *buffer = pattern->buffer;
|
||||
bool_t *end = buffer + (pattern->width * pattern->height);
|
||||
|
||||
while (buffer < end)
|
||||
*buffer++ = xorwow_float (s) < fraction;
|
||||
}
|
||||
|
||||
void
|
||||
pattern_destroy (pattern_t *pattern)
|
||||
{
|
||||
free (pattern->buffer);
|
||||
}
|
||||
|
||||
/* Dither arrays */
|
||||
typedef struct array_t {
|
||||
int width;
|
||||
int height;
|
||||
uint32_t *buffer;
|
||||
} array_t;
|
||||
|
||||
bool_t
|
||||
array_init (array_t *array, int width, int height)
|
||||
{
|
||||
uint32_t *buffer;
|
||||
|
||||
if (!array)
|
||||
return FALSE;
|
||||
|
||||
buffer = malloc_abc (width, height, sizeof (uint32_t));
|
||||
|
||||
if (!buffer)
|
||||
return FALSE;
|
||||
|
||||
array->buffer = buffer;
|
||||
array->width = width;
|
||||
array->height = height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint32_t *
|
||||
array_get (array_t *array, int x, int y)
|
||||
{
|
||||
return &array->buffer[y * array->width + x];
|
||||
}
|
||||
|
||||
bool_t
|
||||
array_save_ppm (array_t *array, const char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "wb");
|
||||
|
||||
int i = 0;
|
||||
int bpp = 2;
|
||||
uint8_t buffer[1024];
|
||||
|
||||
if (!f)
|
||||
return FALSE;
|
||||
|
||||
if (array->width * array->height - 1 < 256)
|
||||
bpp = 1;
|
||||
|
||||
fprintf(f, "P5 %d %d %d\n", array->width, array->height,
|
||||
array->width * array->height - 1);
|
||||
while (i < array->width * array->height)
|
||||
{
|
||||
int j = 0;
|
||||
for (; j < 1024 / bpp && j < array->width * array->height; ++j)
|
||||
{
|
||||
uint32_t v = array->buffer[i + j];
|
||||
if (bpp == 2)
|
||||
{
|
||||
buffer[2 * j] = v & 0xff;
|
||||
buffer[2 * j + 1] = (v & 0xff00) >> 8;
|
||||
} else {
|
||||
buffer[j] = v;
|
||||
}
|
||||
}
|
||||
|
||||
fwrite((void *)buffer, bpp, j, f);
|
||||
i += j;
|
||||
}
|
||||
|
||||
if (fclose(f) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
array_save (array_t *array, const char *filename)
|
||||
{
|
||||
int x, y;
|
||||
FILE *f = fopen(filename, "wb");
|
||||
|
||||
if (!f)
|
||||
return FALSE;
|
||||
|
||||
fprintf (f,
|
||||
"/* WARNING: This file is generated by make-blue-noise.c\n"
|
||||
" * Please edit that file instead of this one.\n"
|
||||
" */\n"
|
||||
"\n"
|
||||
"#ifndef BLUE_NOISE_%dX%d_H\n"
|
||||
"#define BLUE_NOISE_%dX%d_H\n"
|
||||
"\n"
|
||||
"#include <stdint.h>\n"
|
||||
"\n", array->width, array->height, array->width, array->height);
|
||||
|
||||
fprintf (f, "static const uint16_t dither_blue_noise_%dx%d[%d] = {\n",
|
||||
array->width, array->height, array->width * array->height);
|
||||
|
||||
for (y = 0; y < array->height; ++y)
|
||||
{
|
||||
fprintf (f, " ");
|
||||
for (x = 0; x < array->width; ++x)
|
||||
{
|
||||
if (x != 0)
|
||||
fprintf (f, ", ");
|
||||
|
||||
fprintf (f, "%d", *array_get (array, x, y));
|
||||
}
|
||||
|
||||
fprintf (f, ",\n");
|
||||
}
|
||||
fprintf (f, "};\n");
|
||||
|
||||
fprintf (f, "\n#endif /* BLUE_NOISE_%dX%d_H */\n",
|
||||
array->width, array->height);
|
||||
|
||||
if (fclose(f) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
array_destroy (array_t *array)
|
||||
{
|
||||
free (array->buffer);
|
||||
}
|
||||
|
||||
/* Dither array generation */
|
||||
bool_t
|
||||
compute_cluster_sizes (pattern_t *pattern, matrix_t *matrix)
|
||||
{
|
||||
int width = pattern->width,
|
||||
height = pattern->height;
|
||||
|
||||
if (matrix->width != width || matrix->height != height)
|
||||
return FALSE;
|
||||
|
||||
int px, py, qx, qy, dx, dy;
|
||||
float tsqsi = 2.f * 1.5f * 1.5f;
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel for default (none) \
|
||||
private (py, px, qy, qx, dx, dy) \
|
||||
shared (height, width, pattern, matrix, tsqsi)
|
||||
#endif
|
||||
for (py = 0; py < height; ++py)
|
||||
{
|
||||
for (px = 0; px < width; ++px)
|
||||
{
|
||||
bool_t pixel = *pattern_get (pattern, px, py);
|
||||
float dist = 0.f;
|
||||
|
||||
for (qx = 0; qx < width; ++qx)
|
||||
{
|
||||
dx = imin (abs (qx - px), width - abs (qx - px));
|
||||
dx = dx * dx;
|
||||
|
||||
for (qy = 0; qy < height; ++qy)
|
||||
{
|
||||
dy = imin (abs (qy - py), height - abs (qy - py));
|
||||
dy = dy * dy;
|
||||
|
||||
dist += (pixel == *pattern_get (pattern, qx, qy))
|
||||
* expf (- (dx + dy) / tsqsi);
|
||||
}
|
||||
}
|
||||
|
||||
*matrix_get (matrix, px, py) = dist;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
swap_pixel (pattern_t *pattern, matrix_t *matrix, int x, int y)
|
||||
{
|
||||
int width = pattern->width,
|
||||
height = pattern->height;
|
||||
|
||||
bool_t new;
|
||||
|
||||
float f,
|
||||
dist = 0.f,
|
||||
tsqsi = 2.f * 1.5f * 1.5f;
|
||||
|
||||
int px, py, dx, dy;
|
||||
bool_t b;
|
||||
|
||||
new = !*pattern_get (pattern, x, y);
|
||||
*pattern_get (pattern, x, y) = new;
|
||||
|
||||
if (matrix->width != width || matrix->height != height)
|
||||
return FALSE;
|
||||
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel for reduction (+:dist) default (none) \
|
||||
private (px, py, dx, dy, b, f) \
|
||||
shared (x, y, width, height, pattern, matrix, new, tsqsi)
|
||||
#endif
|
||||
for (py = 0; py < height; ++py)
|
||||
{
|
||||
dy = imin (abs (py - y), height - abs (py - y));
|
||||
dy = dy * dy;
|
||||
|
||||
for (px = 0; px < width; ++px)
|
||||
{
|
||||
dx = imin (abs (px - x), width - abs (px - x));
|
||||
dx = dx * dx;
|
||||
|
||||
b = (*pattern_get (pattern, px, py) == new);
|
||||
f = expf (- (dx + dy) / tsqsi);
|
||||
*matrix_get (matrix, px, py) += (2 * b - 1) * f;
|
||||
|
||||
dist += b * f;
|
||||
}
|
||||
}
|
||||
|
||||
*matrix_get (matrix, x, y) = dist;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
largest_cluster (pattern_t *pattern, matrix_t *matrix,
|
||||
bool_t pixel, int *xmax, int *ymax)
|
||||
{
|
||||
int width = pattern->width,
|
||||
height = pattern->height;
|
||||
|
||||
int x, y;
|
||||
|
||||
float vmax = -INFINITY;
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel default (none) \
|
||||
private (x, y) \
|
||||
shared (height, width, pattern, matrix, pixel, xmax, ymax, vmax)
|
||||
#endif
|
||||
{
|
||||
int xbest = -1,
|
||||
ybest = -1;
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
float vbest = -INFINITY;
|
||||
|
||||
#pragma omp for reduction (max: vmax) collapse (2)
|
||||
#endif
|
||||
for (y = 0; y < height; ++y)
|
||||
{
|
||||
for (x = 0; x < width; ++x)
|
||||
{
|
||||
if (*pattern_get (pattern, x, y) != pixel)
|
||||
continue;
|
||||
|
||||
if (*matrix_get (matrix, x, y) > vmax)
|
||||
{
|
||||
vmax = *matrix_get (matrix, x, y);
|
||||
#ifdef USE_OPENMP
|
||||
vbest = vmax;
|
||||
#endif
|
||||
xbest = x;
|
||||
ybest = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp barrier
|
||||
#pragma omp critical
|
||||
{
|
||||
if (vmax == vbest)
|
||||
{
|
||||
*xmax = xbest;
|
||||
*ymax = ybest;
|
||||
}
|
||||
}
|
||||
#else
|
||||
*xmax = xbest;
|
||||
*ymax = ybest;
|
||||
#endif
|
||||
}
|
||||
|
||||
assert (vmax > -INFINITY);
|
||||
}
|
||||
|
||||
void
|
||||
generate_initial_binary_pattern (pattern_t *pattern, matrix_t *matrix)
|
||||
{
|
||||
int xcluster = 0,
|
||||
ycluster = 0,
|
||||
xvoid = 0,
|
||||
yvoid = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
largest_cluster (pattern, matrix, TRUE, &xcluster, &ycluster);
|
||||
assert (*pattern_get (pattern, xcluster, ycluster) == TRUE);
|
||||
swap_pixel (pattern, matrix, xcluster, ycluster);
|
||||
|
||||
largest_cluster (pattern, matrix, FALSE, &xvoid, &yvoid);
|
||||
assert (*pattern_get (pattern, xvoid, yvoid) == FALSE);
|
||||
swap_pixel (pattern, matrix, xvoid, yvoid);
|
||||
|
||||
if (xcluster == xvoid && ycluster == yvoid)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t
|
||||
generate_dither_array (array_t *array,
|
||||
pattern_t const *prototype, matrix_t const *matrix,
|
||||
pattern_t *temp_pattern, matrix_t *temp_matrix)
|
||||
{
|
||||
int width = prototype->width,
|
||||
height = prototype->height;
|
||||
|
||||
int x, y, rank;
|
||||
|
||||
int initial_rank = 0;
|
||||
|
||||
if (array->width != width || array->height != height)
|
||||
return FALSE;
|
||||
|
||||
// Make copies of the prototype and associated sizes matrix since we will
|
||||
// trash them
|
||||
if (!pattern_copy (temp_pattern, prototype))
|
||||
return FALSE;
|
||||
|
||||
if (!matrix_copy (temp_matrix, matrix))
|
||||
return FALSE;
|
||||
|
||||
// Compute initial rank
|
||||
for (y = 0; y < height; ++y)
|
||||
{
|
||||
for (x = 0; x < width; ++x)
|
||||
{
|
||||
if (*pattern_get (temp_pattern, x, y))
|
||||
initial_rank += 1;
|
||||
|
||||
*array_get (array, x, y) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 1
|
||||
for (rank = initial_rank; rank > 0; --rank)
|
||||
{
|
||||
largest_cluster (temp_pattern, temp_matrix, TRUE, &x, &y);
|
||||
swap_pixel (temp_pattern, temp_matrix, x, y);
|
||||
*array_get (array, x, y) = rank - 1;
|
||||
}
|
||||
|
||||
// Make copies again for phases 2 & 3
|
||||
if (!pattern_copy (temp_pattern, prototype))
|
||||
return FALSE;
|
||||
|
||||
if (!matrix_copy (temp_matrix, matrix))
|
||||
return FALSE;
|
||||
|
||||
// Phase 2 & 3
|
||||
for (rank = initial_rank; rank < width * height; ++rank)
|
||||
{
|
||||
largest_cluster (temp_pattern, temp_matrix, FALSE, &x, &y);
|
||||
swap_pixel (temp_pattern, temp_matrix, x, y);
|
||||
*array_get (array, x, y) = rank;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
generate (int size, xorwow_state_t *s,
|
||||
char const *c_filename, char const *ppm_filename)
|
||||
{
|
||||
bool_t ok = TRUE;
|
||||
|
||||
pattern_t prototype, temp_pattern;
|
||||
array_t array;
|
||||
matrix_t matrix, temp_matrix;
|
||||
|
||||
printf ("Generating %dx%d blue noise...\n", size, size);
|
||||
|
||||
if (!pattern_init (&prototype, size, size))
|
||||
return FALSE;
|
||||
|
||||
if (!pattern_init (&temp_pattern, size, size))
|
||||
{
|
||||
pattern_destroy (&prototype);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!matrix_init (&matrix, size, size))
|
||||
{
|
||||
pattern_destroy (&temp_pattern);
|
||||
pattern_destroy (&prototype);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!matrix_init (&temp_matrix, size, size))
|
||||
{
|
||||
matrix_destroy (&matrix);
|
||||
pattern_destroy (&temp_pattern);
|
||||
pattern_destroy (&prototype);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!array_init (&array, size, size))
|
||||
{
|
||||
matrix_destroy (&temp_matrix);
|
||||
matrix_destroy (&matrix);
|
||||
pattern_destroy (&temp_pattern);
|
||||
pattern_destroy (&prototype);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
printf("Filling initial binary pattern with white noise...\n");
|
||||
pattern_fill_white_noise (&prototype, .1, s);
|
||||
|
||||
printf("Initializing cluster sizes...\n");
|
||||
if (!compute_cluster_sizes (&prototype, &matrix))
|
||||
{
|
||||
fprintf (stderr, "Error while computing cluster sizes\n");
|
||||
ok = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Generating initial binary pattern...\n");
|
||||
generate_initial_binary_pattern (&prototype, &matrix);
|
||||
|
||||
printf("Generating dither array...\n");
|
||||
if (!generate_dither_array (&array, &prototype, &matrix,
|
||||
&temp_pattern, &temp_matrix))
|
||||
{
|
||||
fprintf (stderr, "Error while generating dither array\n");
|
||||
ok = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Saving dither array...\n");
|
||||
if (!array_save (&array, c_filename))
|
||||
{
|
||||
fprintf (stderr, "Error saving dither array\n");
|
||||
ok = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if SAVE_PPM
|
||||
if (!array_save_ppm (&array, ppm_filename))
|
||||
{
|
||||
fprintf (stderr, "Error saving dither array PPM\n");
|
||||
ok = FALSE;
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
(void)ppm_filename;
|
||||
#endif
|
||||
|
||||
printf("All done!\n");
|
||||
|
||||
out:
|
||||
array_destroy (&array);
|
||||
matrix_destroy (&temp_matrix);
|
||||
matrix_destroy (&matrix);
|
||||
pattern_destroy (&temp_pattern);
|
||||
pattern_destroy (&prototype);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
xorwow_state_t s = {1185956906, 12385940, 983948, 349208051, 901842};
|
||||
|
||||
if (!generate (64, &s, "blue-noise-64x64.h", "blue-noise-64x64.ppm"))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
412
gfx/cairo/libpixman/src/loongson-mmintrin.h
Normal file
412
gfx/cairo/libpixman/src/loongson-mmintrin.h
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
/* The gcc-provided loongson intrinsic functions are way too fucking broken
|
||||
* to be of any use, otherwise I'd use them.
|
||||
*
|
||||
* - The hardware instructions are very similar to MMX or iwMMXt. Certainly
|
||||
* close enough that they could have implemented the _mm_*-style intrinsic
|
||||
* interface and had a ton of optimized code available to them. Instead they
|
||||
* implemented something much, much worse.
|
||||
*
|
||||
* - pshuf takes a dead first argument, causing extra instructions to be
|
||||
* generated.
|
||||
*
|
||||
* - There are no 64-bit shift or logical intrinsics, which means you have
|
||||
* to implement them with inline assembly, but this is a nightmare because
|
||||
* gcc doesn't understand that the integer vector datatypes are actually in
|
||||
* floating-point registers, so you end up with braindead code like
|
||||
*
|
||||
* punpcklwd $f9,$f9,$f5
|
||||
* dmtc1 v0,$f8
|
||||
* punpcklwd $f19,$f19,$f5
|
||||
* dmfc1 t9,$f9
|
||||
* dmtc1 v0,$f9
|
||||
* dmtc1 t9,$f20
|
||||
* dmfc1 s0,$f19
|
||||
* punpcklbh $f20,$f20,$f2
|
||||
*
|
||||
* where crap just gets copied back and forth between integer and floating-
|
||||
* point registers ad nauseum.
|
||||
*
|
||||
* Instead of trying to workaround the problems from these crap intrinsics, I
|
||||
* just implement the _mm_* intrinsics needed for pixman-mmx.c using inline
|
||||
* assembly.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* vectors are stored in 64-bit floating-point registers */
|
||||
typedef double __m64;
|
||||
/* having a 32-bit datatype allows us to use 32-bit loads in places like load8888 */
|
||||
typedef float __m32;
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_setzero_si64 (void)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_add_pi16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("paddh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_add_pi32 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("paddw %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_adds_pu16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("paddush %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_adds_pu8 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("paddusb %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_and_si64 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("and %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pcmpeqw %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_empty (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_madd_pi16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pmaddhw %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mulhi_pu16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pmulhuh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_mullo_pi16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pmullh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_or_si64 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("or %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_packs_pu16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("packushb %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_packs_pi32 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("packsswh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
|
||||
(((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0))
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_set_pi16 (uint16_t __w3, uint16_t __w2, uint16_t __w1, uint16_t __w0)
|
||||
{
|
||||
if (__builtin_constant_p (__w3) &&
|
||||
__builtin_constant_p (__w2) &&
|
||||
__builtin_constant_p (__w1) &&
|
||||
__builtin_constant_p (__w0))
|
||||
{
|
||||
uint64_t val = ((uint64_t)__w3 << 48)
|
||||
| ((uint64_t)__w2 << 32)
|
||||
| ((uint64_t)__w1 << 16)
|
||||
| ((uint64_t)__w0 << 0);
|
||||
return *(__m64 *)&val;
|
||||
}
|
||||
else if (__w3 == __w2 && __w2 == __w1 && __w1 == __w0)
|
||||
{
|
||||
/* TODO: handle other cases */
|
||||
uint64_t val = __w3;
|
||||
uint64_t imm = _MM_SHUFFLE (0, 0, 0, 0);
|
||||
__m64 ret;
|
||||
asm("pshufh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (*(__m64 *)&val), "f" (*(__m64 *)&imm)
|
||||
);
|
||||
return ret;
|
||||
} else {
|
||||
uint64_t val = ((uint64_t)__w3 << 48)
|
||||
| ((uint64_t)__w2 << 32)
|
||||
| ((uint64_t)__w1 << 16)
|
||||
| ((uint64_t)__w0 << 0);
|
||||
return *(__m64 *)&val;
|
||||
}
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_set_pi32 (unsigned __i1, unsigned __i0)
|
||||
{
|
||||
if (__builtin_constant_p (__i1) &&
|
||||
__builtin_constant_p (__i0))
|
||||
{
|
||||
uint64_t val = ((uint64_t)__i1 << 32)
|
||||
| ((uint64_t)__i0 << 0);
|
||||
return *(__m64 *)&val;
|
||||
}
|
||||
else if (__i1 == __i0)
|
||||
{
|
||||
uint64_t imm = _MM_SHUFFLE (1, 0, 1, 0);
|
||||
__m64 ret;
|
||||
asm("pshufh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (*(__m32 *)&__i1), "f" (*(__m64 *)&imm)
|
||||
);
|
||||
return ret;
|
||||
} else {
|
||||
uint64_t val = ((uint64_t)__i1 << 32)
|
||||
| ((uint64_t)__i0 << 0);
|
||||
return *(__m64 *)&val;
|
||||
}
|
||||
}
|
||||
#undef _MM_SHUFFLE
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_shuffle_pi16 (__m64 __m, int64_t __n)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pshufh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__n)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_slli_pi16 (__m64 __m, int64_t __count)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("psllh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__count)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_slli_si64 (__m64 __m, int64_t __count)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("dsll %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__count)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_srli_pi16 (__m64 __m, int64_t __count)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("psrlh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__count)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_srli_pi32 (__m64 __m, int64_t __count)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("psrlw %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__count)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_srli_si64 (__m64 __m, int64_t __count)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("dsrl %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__count)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_sub_pi16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("psubh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("punpckhbh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("punpckhhw %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("punpcklbh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Since punpcklbh doesn't care about the high 32-bits, we use the __m32 datatype which
|
||||
* allows load8888 to use 32-bit loads */
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_unpacklo_pi8_f (__m32 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("punpcklbh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("punpcklhw %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_xor_si64 (__m64 __m1, __m64 __m2)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("xor %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
loongson_extract_pi16 (__m64 __m, int64_t __pos)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pextrh %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m), "f" (*(__m64 *)&__pos)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
loongson_insert_pi16 (__m64 __m1, __m64 __m2, int64_t __pos)
|
||||
{
|
||||
__m64 ret;
|
||||
asm("pinsrh_%3 %0, %1, %2\n\t"
|
||||
: "=f" (ret)
|
||||
: "f" (__m1), "f" (__m2), "i" (__pos)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
$usage = "Usage: combine.pl { 8 | 16 } < pixman-combine.c.template";
|
||||
|
||||
$#ARGV == 0 or die $usage;
|
||||
|
||||
# Get the component size.
|
||||
$size = int($ARGV[0]);
|
||||
$size == 8 or $size == 16 or die $usage;
|
||||
|
||||
$pixel_size = $size * 4;
|
||||
$half_pixel_size = $size * 2;
|
||||
|
||||
sub mask {
|
||||
my $str = shift;
|
||||
my $suffix;
|
||||
$suffix = "ULL" if $size > 8;
|
||||
|
||||
return "0x" . $str . $suffix;
|
||||
}
|
||||
|
||||
# Generate mask strings.
|
||||
$nibbles = $size / 4;
|
||||
$mask = "f" x $nibbles;
|
||||
$zero_mask = "0" x $nibbles;
|
||||
$one_half = "8" . "0" x ($nibbles - 1);
|
||||
|
||||
print "/* WARNING: This file is generated by combine.pl from combine.inc.\n";
|
||||
print " Please edit one of those files rather than this one. */\n";
|
||||
print "\n";
|
||||
|
||||
print "#line 1 \"pixman-combine.c.template\"\n";
|
||||
|
||||
$mask_ = mask($mask);
|
||||
$one_half_ = mask($one_half);
|
||||
$g_mask = mask($mask . $zero_mask);
|
||||
$b_mask = mask($mask . $zero_mask x 2);
|
||||
$a_mask = mask($mask . $zero_mask x 3);
|
||||
$rb_mask = mask($mask . $zero_mask . $mask);
|
||||
$ag_mask = mask($mask . $zero_mask . $mask . $zero_mask);
|
||||
$rb_one_half = mask($one_half . $zero_mask . $one_half);
|
||||
$rb_mask_plus_one = mask("1" . $zero_mask x 2 . "1" . $zero_mask);
|
||||
|
||||
while (<STDIN>) {
|
||||
# Mask and 1/2 value for a single component.
|
||||
s/#define COMPONENT_SIZE\b/$& $size/;
|
||||
s/#define MASK\b/$& $mask_/;
|
||||
s/#define ONE_HALF\b/$& $one_half_/;
|
||||
|
||||
# Shifts and masks for green, blue, and alpha.
|
||||
s/#define G_SHIFT\b/$& $size/;
|
||||
s/#define R_SHIFT\b/$& $size * 2/;
|
||||
s/#define A_SHIFT\b/$& $size * 3/;
|
||||
s/#define G_MASK\b/$& $g_mask/;
|
||||
s/#define R_MASK\b/$& $b_mask/;
|
||||
s/#define A_MASK\b/$& $a_mask/;
|
||||
|
||||
# Special values for dealing with red + blue at the same time.
|
||||
s/#define RB_MASK\b/$& $rb_mask/;
|
||||
s/#define AG_MASK\b/$& $ag_mask/;
|
||||
s/#define RB_ONE_HALF\b/$& $rb_one_half/;
|
||||
s/#define RB_MASK_PLUS_ONE\b/$& $rb_mask_plus_one/;
|
||||
|
||||
# Add 32/64 suffix to combining function types.
|
||||
s/\bCombineFunc\b/CombineFunc$pixel_size/;
|
||||
s/\bFbComposeFunctions\b/FbComposeFunctions$pixel_size/;
|
||||
s/combine_width/combine_$pixel_size/;
|
||||
s/_pixman_setup_combiner_functions_width/_pixman_setup_combiner_functions_$pixel_size/;
|
||||
s/UNc/UN$size/g;
|
||||
s/ALPHA_c/ALPHA_$size/g;
|
||||
s/RED_c/RED_$size/g;
|
||||
s/GREEN_c/GREEN_$size/g;
|
||||
s/BLUE_c/BLUE_$size/g;
|
||||
|
||||
# Convert comp*_t values into the appropriate real types.
|
||||
s/comp1_t/uint${size}_t/g;
|
||||
s/comp2_t/uint${half_pixel_size}_t/g;
|
||||
s/comp4_t/uint${pixel_size}_t/g;
|
||||
|
||||
# Change the function table name for the 64-bit version.
|
||||
s/pixman_composeFunctions/pixman_composeFunctions64/ if $size == 16;
|
||||
|
||||
# Change the header for the 64-bit version
|
||||
s/pixman-combine.h/pixman-combine64.h/ if $size == 16;
|
||||
s/pixman-combine.h/pixman-combine32.h/ if $size == 8;
|
||||
|
||||
print;
|
||||
}
|
||||
129
gfx/cairo/libpixman/src/meson.build
Normal file
129
gfx/cairo/libpixman/src/meson.build
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# Copyright © 2018 Intel Corporation
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
config_h = configure_file(
|
||||
configuration : config,
|
||||
output : 'config.h'
|
||||
)
|
||||
|
||||
version_h = configure_file(
|
||||
configuration : version_conf,
|
||||
input : 'pixman-version.h.in',
|
||||
output : 'pixman-version.h',
|
||||
install_dir : join_paths(get_option('prefix'), get_option('includedir'), 'pixman-1')
|
||||
)
|
||||
|
||||
libpixman_extra_cargs = []
|
||||
if cc.has_function_attribute('dllexport')
|
||||
libpixman_extra_cargs = ['-DPIXMAN_API=__declspec(dllexport)']
|
||||
endif
|
||||
|
||||
pixman_simd_libs = []
|
||||
simds = [
|
||||
# the mmx library can be compiled with mmx on x86/x86_64, iwmmxt on
|
||||
# some arm cores, or loongson mmi on loongson mips systems. The
|
||||
# libraries will all have the same name, "pixman-mmx", but there is
|
||||
# no chance of more than one version being built in the same build
|
||||
# because no system could have mmx, iwmmxt, and mmi, and it
|
||||
# simplifies the build logic to give them the same name.
|
||||
['mmx', have_mmx, mmx_flags, []],
|
||||
['mmx', have_loongson_mmi, loongson_mmi_flags, []],
|
||||
['mmx', have_iwmmxt, iwmmxt_flags, []],
|
||||
|
||||
['sse2', have_sse2, sse2_flags, []],
|
||||
['ssse3', have_ssse3, ssse3_flags, []],
|
||||
['vmx', have_vmx, vmx_flags, []],
|
||||
['arm-simd', have_armv6_simd, [],
|
||||
['pixman-arm-simd-asm.S', 'pixman-arm-simd-asm-scaled.S']],
|
||||
['arm-neon', have_neon, [],
|
||||
['pixman-arm-neon-asm.S', 'pixman-arm-neon-asm-bilinear.S']],
|
||||
['mips-dspr2', have_mips_dspr2, mips_dspr2_flags,
|
||||
['pixman-mips-dspr2-asm.S', 'pixman-mips-memcpy-asm.S']],
|
||||
]
|
||||
|
||||
foreach simd : simds
|
||||
if simd[1]
|
||||
name = 'pixman-' + simd[0]
|
||||
pixman_simd_libs += static_library(
|
||||
name,
|
||||
[name + '.c', config_h, version_h, simd[3]],
|
||||
c_args : simd[2]
|
||||
)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
pixman_files = files(
|
||||
'pixman.c',
|
||||
'pixman-access.c',
|
||||
'pixman-access-accessors.c',
|
||||
'pixman-bits-image.c',
|
||||
'pixman-combine32.c',
|
||||
'pixman-combine-float.c',
|
||||
'pixman-conical-gradient.c',
|
||||
'pixman-filter.c',
|
||||
'pixman-x86.c',
|
||||
'pixman-mips.c',
|
||||
'pixman-arm.c',
|
||||
'pixman-ppc.c',
|
||||
'pixman-edge.c',
|
||||
'pixman-edge-accessors.c',
|
||||
'pixman-fast-path.c',
|
||||
'pixman-glyph.c',
|
||||
'pixman-general.c',
|
||||
'pixman-gradient-walker.c',
|
||||
'pixman-image.c',
|
||||
'pixman-implementation.c',
|
||||
'pixman-linear-gradient.c',
|
||||
'pixman-matrix.c',
|
||||
'pixman-noop.c',
|
||||
'pixman-radial-gradient.c',
|
||||
'pixman-region16.c',
|
||||
'pixman-region32.c',
|
||||
'pixman-solid-fill.c',
|
||||
'pixman-timer.c',
|
||||
'pixman-trap.c',
|
||||
'pixman-utils.c',
|
||||
)
|
||||
|
||||
# We cannot use 'link_with' or 'link_whole' because meson wont do the right
|
||||
# thing for static archives.
|
||||
_obs = []
|
||||
foreach l : pixman_simd_libs
|
||||
_obs += l.extract_all_objects()
|
||||
endforeach
|
||||
|
||||
libpixman = library(
|
||||
'pixman-1',
|
||||
[pixman_files, config_h, version_h],
|
||||
objects : _obs,
|
||||
c_args : libpixman_extra_cargs,
|
||||
dependencies : [dep_m, dep_threads],
|
||||
version : meson.project_version(),
|
||||
install : true,
|
||||
)
|
||||
|
||||
inc_pixman = include_directories('.')
|
||||
|
||||
idep_pixman = declare_dependency(
|
||||
link_with: libpixman,
|
||||
include_directories : inc_pixman,
|
||||
)
|
||||
|
||||
install_headers('pixman.h', subdir : 'pixman-1')
|
||||
|
|
@ -30,7 +30,6 @@ SOURCES += [
|
|||
'pixman-arm.c',
|
||||
'pixman-bits-image.c',
|
||||
'pixman-combine-float.c',
|
||||
'pixman-combine16.c',
|
||||
'pixman-combine32.c',
|
||||
'pixman-conical-gradient.c',
|
||||
'pixman-edge-accessors.c',
|
||||
|
|
@ -66,10 +65,7 @@ LOCAL_INCLUDES += [
|
|||
]
|
||||
|
||||
if CONFIG['MOZ_USE_PTHREADS']:
|
||||
DEFINES['HAVE_PTHREAD_SETSPECIFIC'] = True
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
DEFINES['PIXMAN_USE_XP_DLL_TLS_WORKAROUND'] = True
|
||||
DEFINES['HAVE_PTHREADS'] = True
|
||||
|
||||
DEFINES['PACKAGE'] = 'mozpixman'
|
||||
|
||||
|
|
@ -103,8 +99,8 @@ if use_mmx:
|
|||
if CONFIG['GNU_CC']:
|
||||
SOURCES['pixman-mmx.c'].flags += [
|
||||
'-Winline',
|
||||
'--param inline-unit-growth=10000',
|
||||
'--param large-function-growth=10000',
|
||||
'--param', 'inline-unit-growth=10000',
|
||||
'--param', 'large-function-growth=10000',
|
||||
]
|
||||
|
||||
if use_sse2:
|
||||
|
|
@ -135,6 +131,7 @@ if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
|
|||
'-Wno-address',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-incompatible-pointer-types',
|
||||
'-Wno-unused', # too many unused warnings; ignore
|
||||
]
|
||||
if CONFIG['CLANG_CXX'] or CONFIG['CLANG_CL']:
|
||||
|
|
|
|||
|
|
@ -68,14 +68,14 @@
|
|||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define FETCH_24(img,l,o) \
|
||||
((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16) | \
|
||||
(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \
|
||||
(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0))
|
||||
((uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16) | \
|
||||
(uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \
|
||||
(uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0))
|
||||
#else
|
||||
#define FETCH_24(img,l,o) \
|
||||
((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0) | \
|
||||
(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \
|
||||
(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 16))
|
||||
((uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0) | \
|
||||
(uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \
|
||||
(uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 16))
|
||||
#endif
|
||||
|
||||
/* Store macros */
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
uint32_t *__d = ((uint32_t *)(l)) + ((o) >> 5); \
|
||||
uint32_t __m, __v; \
|
||||
\
|
||||
__m = 1 << (0x1f - ((o) & 0x1f)); \
|
||||
__m = 1U << (0x1f - ((o) & 0x1f)); \
|
||||
__v = (v)? __m : 0; \
|
||||
\
|
||||
WRITE((img), __d, (READ((img), __d) & ~__m) | __v); \
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
uint32_t *__d = ((uint32_t *)(l)) + ((o) >> 5); \
|
||||
uint32_t __m, __v; \
|
||||
\
|
||||
__m = 1 << ((o) & 0x1f); \
|
||||
__m = 1U << ((o) & 0x1f); \
|
||||
__v = (v)? __m : 0; \
|
||||
\
|
||||
WRITE((img), __d, (READ((img), __d) & ~__m) | __v); \
|
||||
|
|
@ -294,14 +294,14 @@ convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixe
|
|||
}
|
||||
|
||||
static force_inline uint32_t
|
||||
convert_pixel_to_a8r8g8b8 (pixman_image_t *image,
|
||||
convert_pixel_to_a8r8g8b8 (bits_image_t *image,
|
||||
pixman_format_code_t format,
|
||||
uint32_t pixel)
|
||||
{
|
||||
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY ||
|
||||
PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
|
||||
{
|
||||
return image->bits.indexed->rgba[pixel];
|
||||
return image->indexed->rgba[pixel];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -332,7 +332,7 @@ convert_pixel_from_a8r8g8b8 (pixman_image_t *image,
|
|||
}
|
||||
|
||||
static force_inline uint32_t
|
||||
fetch_and_convert_pixel (pixman_image_t * image,
|
||||
fetch_and_convert_pixel (bits_image_t * image,
|
||||
const uint8_t * bits,
|
||||
int offset,
|
||||
pixman_format_code_t format)
|
||||
|
|
@ -417,7 +417,7 @@ convert_and_store_pixel (bits_image_t * image,
|
|||
|
||||
#define MAKE_ACCESSORS(format) \
|
||||
static void \
|
||||
fetch_scanline_ ## format (pixman_image_t *image, \
|
||||
fetch_scanline_ ## format (bits_image_t *image, \
|
||||
int x, \
|
||||
int y, \
|
||||
int width, \
|
||||
|
|
@ -425,7 +425,7 @@ convert_and_store_pixel (bits_image_t * image,
|
|||
const uint32_t *mask) \
|
||||
{ \
|
||||
uint8_t *bits = \
|
||||
(uint8_t *)(image->bits.bits + y * image->bits.rowstride); \
|
||||
(uint8_t *)(image->bits + y * image->rowstride); \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < width; ++i) \
|
||||
|
|
@ -461,8 +461,8 @@ convert_and_store_pixel (bits_image_t * image,
|
|||
uint8_t *bits = \
|
||||
(uint8_t *)(image->bits + line * image->rowstride); \
|
||||
\
|
||||
return fetch_and_convert_pixel ((pixman_image_t *)image, \
|
||||
bits, offset, PIXMAN_ ## format); \
|
||||
return fetch_and_convert_pixel ( \
|
||||
image, bits, offset, PIXMAN_ ## format); \
|
||||
} \
|
||||
\
|
||||
static const void *const __dummy__ ## format
|
||||
|
|
@ -583,14 +583,14 @@ to_srgb (float f)
|
|||
}
|
||||
|
||||
static void
|
||||
fetch_scanline_a8r8g8b8_sRGB_float (pixman_image_t *image,
|
||||
fetch_scanline_a8r8g8b8_sRGB_float (bits_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
|
||||
const uint32_t *bits = image->bits + y * image->rowstride;
|
||||
const uint32_t *pixel = bits + x;
|
||||
const uint32_t *end = pixel + width;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
|
@ -612,14 +612,14 @@ fetch_scanline_a8r8g8b8_sRGB_float (pixman_image_t *image,
|
|||
|
||||
/* Expects a float buffer */
|
||||
static void
|
||||
fetch_scanline_a2r10g10b10_float (pixman_image_t *image,
|
||||
fetch_scanline_a2r10g10b10_float (bits_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
|
||||
const uint32_t *bits = image->bits + y * image->rowstride;
|
||||
const uint32_t *pixel = bits + x;
|
||||
const uint32_t *end = pixel + width;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
|
@ -642,15 +642,57 @@ fetch_scanline_a2r10g10b10_float (pixman_image_t *image,
|
|||
}
|
||||
|
||||
/* Expects a float buffer */
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
static void
|
||||
fetch_scanline_x2r10g10b10_float (pixman_image_t *image,
|
||||
fetch_scanline_rgbf_float (bits_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const float *bits = (float *)image->bits + y * image->rowstride;
|
||||
const float *pixel = bits + x * 3;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
||||
for (; width--; buffer++) {
|
||||
buffer->r = *pixel++;
|
||||
buffer->g = *pixel++;
|
||||
buffer->b = *pixel++;
|
||||
buffer->a = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_scanline_rgbaf_float (bits_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const float *bits = (float *)image->bits + y * image->rowstride;
|
||||
const float *pixel = bits + x * 4;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
||||
for (; width--; buffer++) {
|
||||
buffer->r = *pixel++;
|
||||
buffer->g = *pixel++;
|
||||
buffer->b = *pixel++;
|
||||
buffer->a = *pixel++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
fetch_scanline_x2r10g10b10_float (bits_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
|
||||
const uint32_t *bits = image->bits + y * image->rowstride;
|
||||
const uint32_t *pixel = (uint32_t *)bits + x;
|
||||
const uint32_t *end = pixel + width;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
|
@ -673,14 +715,14 @@ fetch_scanline_x2r10g10b10_float (pixman_image_t *image,
|
|||
|
||||
/* Expects a float buffer */
|
||||
static void
|
||||
fetch_scanline_a2b10g10r10_float (pixman_image_t *image,
|
||||
fetch_scanline_a2b10g10r10_float (bits_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
|
||||
const uint32_t *bits = image->bits + y * image->rowstride;
|
||||
const uint32_t *pixel = bits + x;
|
||||
const uint32_t *end = pixel + width;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
|
@ -704,14 +746,14 @@ fetch_scanline_a2b10g10r10_float (pixman_image_t *image,
|
|||
|
||||
/* Expects a float buffer */
|
||||
static void
|
||||
fetch_scanline_x2b10g10r10_float (pixman_image_t *image,
|
||||
fetch_scanline_x2b10g10r10_float (bits_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
|
||||
const uint32_t *bits = image->bits + y * image->rowstride;
|
||||
const uint32_t *pixel = (uint32_t *)bits + x;
|
||||
const uint32_t *end = pixel + width;
|
||||
argb_t *buffer = (argb_t *)b;
|
||||
|
|
@ -733,14 +775,14 @@ fetch_scanline_x2b10g10r10_float (pixman_image_t *image,
|
|||
}
|
||||
|
||||
static void
|
||||
fetch_scanline_yuy2 (pixman_image_t *image,
|
||||
fetch_scanline_yuy2 (bits_image_t *image,
|
||||
int x,
|
||||
int line,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
|
||||
const uint32_t *bits = image->bits + image->rowstride * line;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
|
|
@ -767,7 +809,7 @@ fetch_scanline_yuy2 (pixman_image_t *image,
|
|||
}
|
||||
|
||||
static void
|
||||
fetch_scanline_yv12 (pixman_image_t *image,
|
||||
fetch_scanline_yv12 (bits_image_t *image,
|
||||
int x,
|
||||
int line,
|
||||
int width,
|
||||
|
|
@ -805,6 +847,40 @@ fetch_scanline_yv12 (pixman_image_t *image,
|
|||
|
||||
/**************************** Pixel wise fetching *****************************/
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
static argb_t
|
||||
fetch_pixel_rgbf_float (bits_image_t *image,
|
||||
int offset,
|
||||
int line)
|
||||
{
|
||||
float *bits = (float *)image->bits + line * image->rowstride;
|
||||
argb_t argb;
|
||||
|
||||
argb.r = bits[offset * 3];
|
||||
argb.g = bits[offset * 3 + 1];
|
||||
argb.b = bits[offset * 3 + 2];
|
||||
argb.a = 1.f;
|
||||
|
||||
return argb;
|
||||
}
|
||||
|
||||
static argb_t
|
||||
fetch_pixel_rgbaf_float (bits_image_t *image,
|
||||
int offset,
|
||||
int line)
|
||||
{
|
||||
float *bits = (float *)image->bits + line * image->rowstride;
|
||||
argb_t argb;
|
||||
|
||||
argb.r = bits[offset * 4];
|
||||
argb.g = bits[offset * 4 + 1];
|
||||
argb.b = bits[offset * 4 + 2];
|
||||
argb.a = bits[offset * 4 + 3];
|
||||
|
||||
return argb;
|
||||
}
|
||||
#endif
|
||||
|
||||
static argb_t
|
||||
fetch_pixel_x2r10g10b10_float (bits_image_t *image,
|
||||
int offset,
|
||||
|
|
@ -962,6 +1038,45 @@ fetch_pixel_yv12 (bits_image_t *image,
|
|||
|
||||
/*********************************** Store ************************************/
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
static void
|
||||
store_scanline_rgbaf_float (bits_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
const uint32_t *v)
|
||||
{
|
||||
float *bits = (float *)image->bits + image->rowstride * y + 4 * x;
|
||||
const argb_t *values = (argb_t *)v;
|
||||
|
||||
for (; width; width--, values++)
|
||||
{
|
||||
*bits++ = values->r;
|
||||
*bits++ = values->g;
|
||||
*bits++ = values->b;
|
||||
*bits++ = values->a;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store_scanline_rgbf_float (bits_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
const uint32_t *v)
|
||||
{
|
||||
float *bits = (float *)image->bits + image->rowstride * y + 3 * x;
|
||||
const argb_t *values = (argb_t *)v;
|
||||
|
||||
for (; width; width--, values++)
|
||||
{
|
||||
*bits++ = values->r;
|
||||
*bits++ = values->g;
|
||||
*bits++ = values->b;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
store_scanline_a2r10g10b10_float (bits_image_t * image,
|
||||
int x,
|
||||
|
|
@ -976,7 +1091,7 @@ store_scanline_a2r10g10b10_float (bits_image_t * image,
|
|||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint16_t a, r, g, b;
|
||||
uint32_t a, r, g, b;
|
||||
|
||||
a = pixman_float_to_unorm (values[i].a, 2);
|
||||
r = pixman_float_to_unorm (values[i].r, 10);
|
||||
|
|
@ -1002,7 +1117,7 @@ store_scanline_x2r10g10b10_float (bits_image_t * image,
|
|||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint16_t r, g, b;
|
||||
uint32_t r, g, b;
|
||||
|
||||
r = pixman_float_to_unorm (values[i].r, 10);
|
||||
g = pixman_float_to_unorm (values[i].g, 10);
|
||||
|
|
@ -1027,7 +1142,7 @@ store_scanline_a2b10g10r10_float (bits_image_t * image,
|
|||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint16_t a, r, g, b;
|
||||
uint32_t a, r, g, b;
|
||||
|
||||
a = pixman_float_to_unorm (values[i].a, 2);
|
||||
r = pixman_float_to_unorm (values[i].r, 10);
|
||||
|
|
@ -1053,7 +1168,7 @@ store_scanline_x2b10g10r10_float (bits_image_t * image,
|
|||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint16_t r, g, b;
|
||||
uint32_t r, g, b;
|
||||
|
||||
r = pixman_float_to_unorm (values[i].r, 10);
|
||||
g = pixman_float_to_unorm (values[i].g, 10);
|
||||
|
|
@ -1078,7 +1193,7 @@ store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image,
|
|||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint8_t a, r, g, b;
|
||||
uint32_t a, r, g, b;
|
||||
|
||||
a = pixman_float_to_unorm (values[i].a, 8);
|
||||
r = to_srgb (values[i].r);
|
||||
|
|
@ -1090,44 +1205,6 @@ store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store_scanline_16 (bits_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
const uint32_t *v)
|
||||
{
|
||||
uint16_t *bits = (uint16_t*)(image->bits + image->rowstride * y);
|
||||
uint16_t *values = (uint16_t *)v;
|
||||
uint16_t *pixel = bits + x;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
WRITE (image, pixel++, values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_scanline_16 (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * b,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint16_t *bits = (uint16_t*)(image->bits.bits + y * image->bits.rowstride);
|
||||
const uint16_t *pixel = bits + x;
|
||||
int i;
|
||||
uint16_t *buffer = (uint16_t *)b;
|
||||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
*buffer++ = READ (image, pixel++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Contracts a floating point image to 32bpp and then stores it using a
|
||||
* regular 32-bit store proc. Despite the type, this function expects an
|
||||
|
|
@ -1159,37 +1236,37 @@ store_scanline_generic_float (bits_image_t * image,
|
|||
}
|
||||
|
||||
static void
|
||||
fetch_scanline_generic_float (pixman_image_t *image,
|
||||
fetch_scanline_generic_float (bits_image_t * image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t * buffer,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
|
||||
image->fetch_scanline_32 (image, x, y, width, buffer, NULL);
|
||||
|
||||
pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width);
|
||||
pixman_expand_to_float ((argb_t *)buffer, buffer, image->format, width);
|
||||
}
|
||||
|
||||
/* The 32_sRGB paths should be deleted after narrow processing
|
||||
* is no longer invoked for formats that are considered wide.
|
||||
* (Also see fetch_pixel_generic_lossy_32) */
|
||||
static void
|
||||
fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image,
|
||||
fetch_scanline_a8r8g8b8_32_sRGB (bits_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
uint32_t *buffer,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
|
||||
const uint32_t *bits = image->bits + y * image->rowstride;
|
||||
const uint32_t *pixel = (uint32_t *)bits + x;
|
||||
const uint32_t *end = pixel + width;
|
||||
uint32_t tmp;
|
||||
|
||||
while (pixel < end)
|
||||
{
|
||||
uint8_t a, r, g, b;
|
||||
uint32_t a, r, g, b;
|
||||
|
||||
tmp = READ (image, pixel++);
|
||||
|
||||
|
|
@ -1213,7 +1290,7 @@ fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
|
|||
{
|
||||
uint32_t *bits = image->bits + line * image->rowstride;
|
||||
uint32_t tmp = READ (image, bits + offset);
|
||||
uint8_t a, r, g, b;
|
||||
uint32_t a, r, g, b;
|
||||
|
||||
a = (tmp >> 24) & 0xff;
|
||||
r = (tmp >> 16) & 0xff;
|
||||
|
|
@ -1242,7 +1319,7 @@ store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image,
|
|||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint8_t a, r, g, b;
|
||||
uint32_t a, r, g, b;
|
||||
|
||||
tmp = values[i];
|
||||
|
||||
|
|
@ -1294,12 +1371,10 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image,
|
|||
typedef struct
|
||||
{
|
||||
pixman_format_code_t format;
|
||||
fetch_scanline_t fetch_scanline_16;
|
||||
fetch_scanline_t fetch_scanline_32;
|
||||
fetch_scanline_t fetch_scanline_float;
|
||||
fetch_pixel_32_t fetch_pixel_32;
|
||||
fetch_pixel_float_t fetch_pixel_float;
|
||||
store_scanline_t store_scanline_16;
|
||||
store_scanline_t store_scanline_32;
|
||||
store_scanline_t store_scanline_float;
|
||||
} format_info_t;
|
||||
|
|
@ -1307,28 +1382,13 @@ typedef struct
|
|||
#define FORMAT_INFO(format) \
|
||||
{ \
|
||||
PIXMAN_ ## format, \
|
||||
NULL, \
|
||||
fetch_scanline_ ## format, \
|
||||
fetch_scanline_generic_float, \
|
||||
fetch_pixel_ ## format, \
|
||||
fetch_pixel_generic_float, \
|
||||
NULL, \
|
||||
store_scanline_ ## format, \
|
||||
store_scanline_generic_float \
|
||||
}
|
||||
#define FORMAT_INFO16(format) \
|
||||
{ \
|
||||
PIXMAN_ ## format, \
|
||||
fetch_scanline_16, \
|
||||
fetch_scanline_ ## format, \
|
||||
fetch_scanline_generic_float, \
|
||||
fetch_pixel_ ## format, \
|
||||
fetch_pixel_generic_float, \
|
||||
store_scanline_16, \
|
||||
store_scanline_ ## format, \
|
||||
store_scanline_generic_float \
|
||||
}
|
||||
|
||||
|
||||
static const format_info_t accessors[] =
|
||||
{
|
||||
|
|
@ -1345,10 +1405,8 @@ static const format_info_t accessors[] =
|
|||
|
||||
/* sRGB formats */
|
||||
{ PIXMAN_a8r8g8b8_sRGB,
|
||||
NULL,
|
||||
fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
|
||||
fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
|
||||
NULL,
|
||||
store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
|
||||
},
|
||||
|
||||
|
|
@ -1357,8 +1415,8 @@ static const format_info_t accessors[] =
|
|||
FORMAT_INFO (b8g8r8),
|
||||
|
||||
/* 16bpp formats */
|
||||
FORMAT_INFO16 (r5g6b5),
|
||||
FORMAT_INFO16 (b5g6r5),
|
||||
FORMAT_INFO (r5g6b5),
|
||||
FORMAT_INFO (b5g6r5),
|
||||
|
||||
FORMAT_INFO (a1r5g5b5),
|
||||
FORMAT_INFO (x1r5g5b5),
|
||||
|
|
@ -1408,37 +1466,48 @@ static const format_info_t accessors[] =
|
|||
FORMAT_INFO (g1),
|
||||
|
||||
/* Wide formats */
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
{ PIXMAN_rgba_float,
|
||||
NULL, fetch_scanline_rgbaf_float,
|
||||
fetch_pixel_generic_lossy_32, fetch_pixel_rgbaf_float,
|
||||
NULL, store_scanline_rgbaf_float },
|
||||
|
||||
{ PIXMAN_rgb_float,
|
||||
NULL, fetch_scanline_rgbf_float,
|
||||
fetch_pixel_generic_lossy_32, fetch_pixel_rgbf_float,
|
||||
NULL, store_scanline_rgbf_float },
|
||||
#endif
|
||||
|
||||
{ PIXMAN_a2r10g10b10,
|
||||
NULL, NULL, fetch_scanline_a2r10g10b10_float,
|
||||
NULL, fetch_scanline_a2r10g10b10_float,
|
||||
fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
|
||||
NULL, NULL, store_scanline_a2r10g10b10_float },
|
||||
NULL, store_scanline_a2r10g10b10_float },
|
||||
|
||||
{ PIXMAN_x2r10g10b10,
|
||||
NULL, NULL, fetch_scanline_x2r10g10b10_float,
|
||||
NULL, fetch_scanline_x2r10g10b10_float,
|
||||
fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
|
||||
NULL, NULL, store_scanline_x2r10g10b10_float },
|
||||
NULL, store_scanline_x2r10g10b10_float },
|
||||
|
||||
{ PIXMAN_a2b10g10r10,
|
||||
NULL, NULL, fetch_scanline_a2b10g10r10_float,
|
||||
NULL, fetch_scanline_a2b10g10r10_float,
|
||||
fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
|
||||
NULL, NULL, store_scanline_a2b10g10r10_float },
|
||||
NULL, store_scanline_a2b10g10r10_float },
|
||||
|
||||
{ PIXMAN_x2b10g10r10,
|
||||
NULL, NULL, fetch_scanline_x2b10g10r10_float,
|
||||
NULL, fetch_scanline_x2b10g10r10_float,
|
||||
fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
|
||||
NULL, NULL, store_scanline_x2b10g10r10_float },
|
||||
NULL, store_scanline_x2b10g10r10_float },
|
||||
|
||||
/* YUV formats */
|
||||
{ PIXMAN_yuy2,
|
||||
NULL, fetch_scanline_yuy2, fetch_scanline_generic_float,
|
||||
fetch_scanline_yuy2, fetch_scanline_generic_float,
|
||||
fetch_pixel_yuy2, fetch_pixel_generic_float,
|
||||
NULL, NULL, NULL },
|
||||
NULL, NULL },
|
||||
|
||||
{ PIXMAN_yv12,
|
||||
NULL, fetch_scanline_yv12, fetch_scanline_generic_float,
|
||||
fetch_scanline_yv12, fetch_scanline_generic_float,
|
||||
fetch_pixel_yv12, fetch_pixel_generic_float,
|
||||
NULL, NULL, NULL },
|
||||
NULL, NULL },
|
||||
|
||||
{ PIXMAN_null },
|
||||
};
|
||||
|
|
@ -1452,12 +1521,10 @@ setup_accessors (bits_image_t *image)
|
|||
{
|
||||
if (info->format == image->format)
|
||||
{
|
||||
image->fetch_scanline_16 = info->fetch_scanline_16;
|
||||
image->fetch_scanline_32 = info->fetch_scanline_32;
|
||||
image->fetch_scanline_float = info->fetch_scanline_float;
|
||||
image->fetch_pixel_32 = info->fetch_pixel_32;
|
||||
image->fetch_pixel_float = info->fetch_pixel_float;
|
||||
image->store_scanline_16 = info->store_scanline_16;
|
||||
image->store_scanline_32 = info->store_scanline_32;
|
||||
image->store_scanline_float = info->store_scanline_float;
|
||||
|
||||
|
|
|
|||
37
gfx/cairo/libpixman/src/pixman-arm-asm.h
Normal file
37
gfx/cairo/libpixman/src/pixman-arm-asm.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright © 2008 Mozilla Corporation
|
||||
* Copyright © 2010 Nokia Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Mozilla Corporation not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Mozilla Corporation makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Jeff Muizelaar (jeff@infidigm.net)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Supplementary macro for setting function attributes */
|
||||
.macro pixman_asm_function fname
|
||||
.func fname
|
||||
.global fname
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.endm
|
||||
|
|
@ -266,13 +266,6 @@ FAST_NEAREST_MAINLOOP (cputype##_##name##_normal_##op, \
|
|||
scaled_nearest_scanline_##cputype##_##name##_##op, \
|
||||
src_type, dst_type, NORMAL)
|
||||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func)
|
||||
|
||||
#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST(flags, cputype, name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
|
|
@ -318,9 +311,7 @@ FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
|
|||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL (op,s,d,func)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -360,16 +351,16 @@ scaled_bilinear_scanline_##cputype##_##name##_##op ( \
|
|||
\
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
|
||||
src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
|
||||
src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
|
||||
src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint32_t, dst_type, NORMAL, \
|
||||
src_type, uint32_t, dst_type, NORMAL, \
|
||||
FLAG_NONE)
|
||||
|
||||
|
||||
|
|
@ -409,19 +400,19 @@ scaled_bilinear_scanline_##cputype##_##name##_##op ( \
|
|||
\
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, COVER, \
|
||||
src_type, uint8_t, dst_type, COVER, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, NONE, \
|
||||
src_type, uint8_t, dst_type, NONE, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, PAD, \
|
||||
src_type, uint8_t, dst_type, PAD, \
|
||||
FLAG_HAVE_NON_SOLID_MASK) \
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
|
||||
scaled_bilinear_scanline_##cputype##_##name##_##op, \
|
||||
NULL, src_type, uint8_t, dst_type, NORMAL, \
|
||||
src_type, uint8_t, dst_type, NORMAL, \
|
||||
FLAG_HAVE_NON_SOLID_MASK)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
area pixman_msvc, code, readonly
|
||||
|
||||
export pixman_msvc_try_arm_simd_op
|
||||
|
||||
pixman_msvc_try_arm_simd_op
|
||||
;; I don't think the msvc arm asm knows how to do SIMD insns
|
||||
;; uqadd8 r3,r3,r3
|
||||
dcd 0xe6633f93
|
||||
mov pc,lr
|
||||
endp
|
||||
|
||||
export pixman_msvc_try_arm_neon_op
|
||||
|
||||
pixman_msvc_try_arm_neon_op
|
||||
;; I don't think the msvc arm asm knows how to do NEON insns
|
||||
;; veor d0,d0,d0
|
||||
dcd 0xf3000110
|
||||
mov pc,lr
|
||||
endp
|
||||
|
||||
end
|
||||
|
|
@ -65,23 +65,13 @@
|
|||
.p2align 2
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-arm-asm.h"
|
||||
#include "pixman-arm-neon-asm.h"
|
||||
|
||||
/*
|
||||
* Bilinear macros from pixman-arm-neon-asm.S
|
||||
*/
|
||||
|
||||
/* Supplementary macro for setting function attributes */
|
||||
.macro pixman_asm_function fname
|
||||
.func fname
|
||||
.global fname
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Bilinear scaling support code which tries to provide pixel fetching, color
|
||||
* format conversion, and interpolation as separate macros which can be used
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
.p2align 2
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-arm-asm.h"
|
||||
#include "pixman-arm-neon-asm.h"
|
||||
|
||||
/* Global configuration options and preferences */
|
||||
|
|
@ -954,7 +955,6 @@ generate_composite_function \
|
|||
*/
|
||||
.macro pixman_composite_over_n_8_0565_init
|
||||
add DUMMY, sp, #ARGS_STACK_OFFSET
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d11[0]}, [DUMMY]
|
||||
vdup.8 d8, d11[0]
|
||||
|
|
@ -982,7 +982,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_over_8888_n_0565_init
|
||||
add DUMMY, sp, #(ARGS_STACK_OFFSET + 8)
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d24[0]}, [DUMMY]
|
||||
vdup.8 d24, d24[3]
|
||||
|
|
@ -1449,7 +1448,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_over_n_8_8888_init
|
||||
add DUMMY, sp, #ARGS_STACK_OFFSET
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d11[0]}, [DUMMY]
|
||||
vdup.8 d8, d11[0]
|
||||
|
|
@ -1521,7 +1519,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_over_n_8_8_init
|
||||
add DUMMY, sp, #ARGS_STACK_OFFSET
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d8[0]}, [DUMMY]
|
||||
vdup.8 d8, d8[3]
|
||||
|
|
@ -1623,7 +1620,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_over_n_8888_8888_ca_init
|
||||
add DUMMY, sp, #ARGS_STACK_OFFSET
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d11[0]}, [DUMMY]
|
||||
vdup.8 d8, d11[0]
|
||||
|
|
@ -1793,7 +1789,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_over_n_8888_0565_ca_init
|
||||
add DUMMY, sp, #ARGS_STACK_OFFSET
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d11[0]}, [DUMMY]
|
||||
vdup.8 d8, d11[0]
|
||||
|
|
@ -1907,7 +1902,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_add_n_8_8_init
|
||||
add DUMMY, sp, #ARGS_STACK_OFFSET
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d11[0]}, [DUMMY]
|
||||
vdup.8 d11, d11[3]
|
||||
|
|
@ -2214,7 +2208,6 @@ generate_composite_function_single_scanline \
|
|||
|
||||
.macro pixman_composite_over_8888_n_8888_init
|
||||
add DUMMY, sp, #48
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d15[0]}, [DUMMY]
|
||||
vdup.8 d15, d15[3]
|
||||
|
|
@ -2587,7 +2580,6 @@ generate_composite_function \
|
|||
|
||||
.macro pixman_composite_over_0565_n_0565_init
|
||||
add DUMMY, sp, #(ARGS_STACK_OFFSET + 8)
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
vld1.32 {d15[0]}, [DUMMY]
|
||||
vdup.8 d15, d15[3]
|
||||
|
|
@ -2839,17 +2831,6 @@ generate_composite_function_nearest_scanline \
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Supplementary macro for setting function attributes */
|
||||
.macro pixman_asm_function fname
|
||||
.func fname
|
||||
.global fname
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Bilinear scaling support code which tries to provide pixel fetching, color
|
||||
* format conversion, and interpolation as separate macros which can be used
|
||||
|
|
@ -3141,16 +3122,13 @@ pixman_asm_function fname
|
|||
TMP4 .req r9
|
||||
STRIDE .req r2
|
||||
|
||||
.fnstart
|
||||
mov ip, sp
|
||||
.save {r4, r5, r6, r7, r8, r9}
|
||||
push {r4, r5, r6, r7, r8, r9}
|
||||
mov PF_OFFS, #prefetch_distance
|
||||
ldmia ip, {WB, X, UX, WIDTH}
|
||||
mul PF_OFFS, PF_OFFS, UX
|
||||
|
||||
.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
.endif
|
||||
|
||||
|
|
@ -3244,7 +3222,6 @@ pixman_asm_function fname
|
|||
.endif
|
||||
pop {r4, r5, r6, r7, r8, r9}
|
||||
bx lr
|
||||
.fnend
|
||||
|
||||
.unreq OUT
|
||||
.unreq TOP
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@
|
|||
* execute simultaneously with NEON and be completely shadowed by it. Thus
|
||||
* we get no performance overhead at all (*). This looks like a very nice
|
||||
* feature of Cortex-A8, if used wisely. We don't have a hardware prefetcher,
|
||||
* but still can implement some rather advanced prefetch logic in sofware
|
||||
* but still can implement some rather advanced prefetch logic in software
|
||||
* for almost zero cost!
|
||||
*
|
||||
* (*) The overhead of the prefetcher is visible when running some trivial
|
||||
|
|
@ -631,16 +631,8 @@ local skip1
|
|||
src_basereg_ = 0, \
|
||||
mask_basereg_ = 24
|
||||
|
||||
.func fname
|
||||
.global fname
|
||||
/* For ELF format also set function visibility to hidden */
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.fnstart
|
||||
.save {r4-r12, lr}
|
||||
pixman_asm_function fname
|
||||
|
||||
push {r4-r12, lr} /* save all registers */
|
||||
|
||||
/*
|
||||
|
|
@ -818,7 +810,6 @@ fname:
|
|||
|
||||
init
|
||||
.if regs_shortage
|
||||
.save {r0, r1}
|
||||
push {r0, r1}
|
||||
.endif
|
||||
subs H, H, #1
|
||||
|
|
@ -904,7 +895,6 @@ fname:
|
|||
.endif
|
||||
cleanup
|
||||
pop {r4-r12, pc} /* exit */
|
||||
.fnend
|
||||
|
||||
.purgem fetch_src_pixblock
|
||||
.purgem pixld_src
|
||||
|
|
@ -949,15 +939,8 @@ fname:
|
|||
src_basereg_ = 0, \
|
||||
mask_basereg_ = 24
|
||||
|
||||
.func fname
|
||||
.global fname
|
||||
/* For ELF format also set function visibility to hidden */
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.fnstart
|
||||
pixman_asm_function fname
|
||||
|
||||
.set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE
|
||||
/*
|
||||
* Make some macro arguments globally visible and accessible
|
||||
|
|
@ -992,7 +975,6 @@ fname:
|
|||
.endm
|
||||
|
||||
ldr UNIT_X, [sp]
|
||||
.save {r4-r8, lr}
|
||||
push {r4-r8, lr}
|
||||
ldr SRC_WIDTH_FIXED, [sp, #(24 + 4)]
|
||||
.if mask_bpp != 0
|
||||
|
|
@ -1108,7 +1090,6 @@ fname:
|
|||
.purgem fetch_src_pixblock
|
||||
.purgem pixld_src
|
||||
|
||||
.fnend
|
||||
.endfunc
|
||||
.endm
|
||||
|
||||
|
|
@ -1135,7 +1116,6 @@ fname:
|
|||
*/
|
||||
|
||||
.macro default_init_need_all_regs
|
||||
.vsave {d8-d15}
|
||||
vpush {d8-d15}
|
||||
.endm
|
||||
|
||||
|
|
|
|||
|
|
@ -145,23 +145,6 @@ PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_0565, SRC,
|
|||
uint16_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, neon, 8888_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
static force_inline void
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC (
|
||||
uint32_t * dst,
|
||||
const uint32_t * mask,
|
||||
const uint32_t * src_top,
|
||||
const uint32_t * src_bottom,
|
||||
int32_t w,
|
||||
int wt,
|
||||
int wb,
|
||||
pixman_fixed_t vx,
|
||||
pixman_fixed_t unit_x,
|
||||
pixman_fixed_t max_vx,
|
||||
pixman_bool_t zero_src)
|
||||
{
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon (dst, src_top, src_bottom, wt, wb, vx, unit_x, w);
|
||||
}
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, neon, 8888_8888, ADD,
|
||||
uint32_t, uint32_t)
|
||||
|
||||
|
|
@ -285,28 +268,6 @@ arm_neon_blt (pixman_implementation_t *imp,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void op_bilinear_over_8888_0565(uint16_t *dst, const uint32_t *mask, const uint32_t *src, int width)
|
||||
{
|
||||
pixman_composite_over_8888_0565_asm_neon (width, 1, dst, 0, src, 0);
|
||||
}
|
||||
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_cover_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
COVER, FLAG_NONE)
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_pad_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
PAD, FLAG_NONE)
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_none_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
NONE, FLAG_NONE)
|
||||
FAST_BILINEAR_MAINLOOP_COMMON (neon_8888_0565_normal_OVER,
|
||||
pixman_scaled_bilinear_scanline_8888_8888_SRC, op_bilinear_over_8888_0565,
|
||||
uint32_t, uint32_t, uint16_t,
|
||||
NORMAL, FLAG_NONE)
|
||||
|
||||
static const pixman_fast_path_t arm_neon_fast_paths[] =
|
||||
{
|
||||
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565),
|
||||
|
|
@ -401,21 +362,21 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8r8g8b8, neon_composite_out_reverse_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8b8g8r8, neon_composite_out_reverse_8_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, neon_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, neon_8888_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, b5g6r5, neon_8888_0565),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, neon_0565_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, neon_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8888),
|
||||
/* Note: NONE repeat is not supported yet */
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
|
||||
|
|
@ -460,8 +421,6 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
|
|||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
|
||||
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
|
||||
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,16 +37,7 @@
|
|||
.altmacro
|
||||
.p2align 2
|
||||
|
||||
/* Supplementary macro for setting function attributes */
|
||||
.macro pixman_asm_function fname
|
||||
.func fname
|
||||
.global fname
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.endm
|
||||
#include "pixman-arm-asm.h"
|
||||
|
||||
/*
|
||||
* Note: This code is only using armv5te instructions (not even armv6),
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
.altmacro
|
||||
.p2align 2
|
||||
|
||||
#include "pixman-arm-asm.h"
|
||||
#include "pixman-arm-simd-asm.h"
|
||||
|
||||
/* A head macro should do all processing which results in an output of up to
|
||||
|
|
@ -303,6 +304,83 @@ generate_composite_function \
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro src_x888_0565_init
|
||||
/* Hold loop invariant in MASK */
|
||||
ldr MASK, =0x001F001F
|
||||
line_saved_regs STRIDE_S, ORIG_W
|
||||
.endm
|
||||
|
||||
.macro src_x888_0565_1pixel s, d
|
||||
and WK&d, MASK, WK&s, lsr #3 @ 00000000000rrrrr00000000000bbbbb
|
||||
and STRIDE_S, WK&s, #0xFC00 @ 0000000000000000gggggg0000000000
|
||||
orr WK&d, WK&d, WK&d, lsr #5 @ 00000000000-----rrrrr000000bbbbb
|
||||
orr WK&d, WK&d, STRIDE_S, lsr #5 @ 00000000000-----rrrrrggggggbbbbb
|
||||
/* Top 16 bits are discarded during the following STRH */
|
||||
.endm
|
||||
|
||||
.macro src_x888_0565_2pixels slo, shi, d, tmp
|
||||
and SCRATCH, WK&shi, #0xFC00 @ 0000000000000000GGGGGG0000000000
|
||||
and WK&tmp, MASK, WK&shi, lsr #3 @ 00000000000RRRRR00000000000BBBBB
|
||||
and WK&shi, MASK, WK&slo, lsr #3 @ 00000000000rrrrr00000000000bbbbb
|
||||
orr WK&tmp, WK&tmp, WK&tmp, lsr #5 @ 00000000000-----RRRRR000000BBBBB
|
||||
orr WK&tmp, WK&tmp, SCRATCH, lsr #5 @ 00000000000-----RRRRRGGGGGGBBBBB
|
||||
and SCRATCH, WK&slo, #0xFC00 @ 0000000000000000gggggg0000000000
|
||||
orr WK&shi, WK&shi, WK&shi, lsr #5 @ 00000000000-----rrrrr000000bbbbb
|
||||
orr WK&shi, WK&shi, SCRATCH, lsr #5 @ 00000000000-----rrrrrggggggbbbbb
|
||||
pkhbt WK&d, WK&shi, WK&tmp, lsl #16 @ RRRRRGGGGGGBBBBBrrrrrggggggbbbbb
|
||||
.endm
|
||||
|
||||
.macro src_x888_0565_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
WK4 .req STRIDE_S
|
||||
WK5 .req STRIDE_M
|
||||
WK6 .req WK3
|
||||
WK7 .req ORIG_W
|
||||
.if numbytes == 16
|
||||
pixld , 16, 4, SRC, 0
|
||||
src_x888_0565_2pixels 4, 5, 0, 0
|
||||
pixld , 8, 4, SRC, 0
|
||||
src_x888_0565_2pixels 6, 7, 1, 1
|
||||
pixld , 8, 6, SRC, 0
|
||||
.else
|
||||
pixld , numbytes*2, 4, SRC, 0
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro src_x888_0565_process_tail cond, numbytes, firstreg
|
||||
.if numbytes == 16
|
||||
src_x888_0565_2pixels 4, 5, 2, 2
|
||||
src_x888_0565_2pixels 6, 7, 3, 4
|
||||
.elseif numbytes == 8
|
||||
src_x888_0565_2pixels 4, 5, 1, 1
|
||||
src_x888_0565_2pixels 6, 7, 2, 2
|
||||
.elseif numbytes == 4
|
||||
src_x888_0565_2pixels 4, 5, 1, 1
|
||||
.else
|
||||
src_x888_0565_1pixel 4, 1
|
||||
.endif
|
||||
.if numbytes == 16
|
||||
pixst , numbytes, 0, DST
|
||||
.else
|
||||
pixst , numbytes, 1, DST
|
||||
.endif
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_src_x888_0565_asm_armv6, 32, 0, 16, \
|
||||
FLAG_DST_WRITEONLY | FLAG_BRANCH_OVER | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH, \
|
||||
3, /* prefetch distance */ \
|
||||
src_x888_0565_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
src_x888_0565_process_head, \
|
||||
src_x888_0565_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro add_8_8_8pixels cond, dst1, dst2
|
||||
uqadd8&cond WK&dst1, WK&dst1, MASK
|
||||
uqadd8&cond WK&dst2, WK&dst2, STRIDE_M
|
||||
|
|
@ -611,3 +689,491 @@ generate_composite_function \
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro over_reverse_n_8888_init
|
||||
ldr SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
ldr MASK, =0x00800080
|
||||
/* Split source pixel into RB/AG parts */
|
||||
uxtb16 STRIDE_S, SRC
|
||||
uxtb16 STRIDE_M, SRC, ror #8
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, MASK, MASK
|
||||
line_saved_regs STRIDE_D, ORIG_W
|
||||
.endm
|
||||
|
||||
.macro over_reverse_n_8888_newline
|
||||
mov STRIDE_D, #0xFF
|
||||
.endm
|
||||
|
||||
.macro over_reverse_n_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
pixld , numbytes, firstreg, DST, 0
|
||||
.endm
|
||||
|
||||
.macro over_reverse_n_8888_1pixel d, is_only
|
||||
teq WK&d, #0
|
||||
beq 8f /* replace with source */
|
||||
bics ORIG_W, STRIDE_D, WK&d, lsr #24
|
||||
.if is_only == 1
|
||||
beq 49f /* skip store */
|
||||
.else
|
||||
beq 9f /* write same value back */
|
||||
.endif
|
||||
mla SCRATCH, STRIDE_S, ORIG_W, MASK /* red/blue */
|
||||
mla ORIG_W, STRIDE_M, ORIG_W, MASK /* alpha/green */
|
||||
uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8
|
||||
uxtab16 ORIG_W, ORIG_W, ORIG_W, ror #8
|
||||
mov SCRATCH, SCRATCH, ror #8
|
||||
sel ORIG_W, SCRATCH, ORIG_W
|
||||
uqadd8 WK&d, WK&d, ORIG_W
|
||||
b 9f
|
||||
8: mov WK&d, SRC
|
||||
9:
|
||||
.endm
|
||||
|
||||
.macro over_reverse_n_8888_tail numbytes, reg1, reg2, reg3, reg4
|
||||
.if numbytes == 4
|
||||
over_reverse_n_8888_1pixel reg1, 1
|
||||
.else
|
||||
and SCRATCH, WK®1, WK®2
|
||||
.if numbytes == 16
|
||||
and SCRATCH, SCRATCH, WK®3
|
||||
and SCRATCH, SCRATCH, WK®4
|
||||
.endif
|
||||
mvns SCRATCH, SCRATCH, asr #24
|
||||
beq 49f /* skip store if all opaque */
|
||||
over_reverse_n_8888_1pixel reg1, 0
|
||||
over_reverse_n_8888_1pixel reg2, 0
|
||||
.if numbytes == 16
|
||||
over_reverse_n_8888_1pixel reg3, 0
|
||||
over_reverse_n_8888_1pixel reg4, 0
|
||||
.endif
|
||||
.endif
|
||||
pixst , numbytes, reg1, DST
|
||||
49:
|
||||
.endm
|
||||
|
||||
.macro over_reverse_n_8888_process_tail cond, numbytes, firstreg
|
||||
over_reverse_n_8888_tail numbytes, firstreg, %(firstreg+1), %(firstreg+2), %(firstreg+3)
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_over_reverse_n_8888_asm_armv6, 0, 0, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH, \
|
||||
3, /* prefetch distance */ \
|
||||
over_reverse_n_8888_init, \
|
||||
over_reverse_n_8888_newline, \
|
||||
nop_macro, /* cleanup */ \
|
||||
over_reverse_n_8888_process_head, \
|
||||
over_reverse_n_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro over_white_8888_8888_ca_init
|
||||
HALF .req SRC
|
||||
TMP0 .req STRIDE_D
|
||||
TMP1 .req STRIDE_S
|
||||
TMP2 .req STRIDE_M
|
||||
TMP3 .req ORIG_W
|
||||
WK4 .req SCRATCH
|
||||
line_saved_regs STRIDE_D, STRIDE_M, ORIG_W
|
||||
ldr SCRATCH, =0x800080
|
||||
mov HALF, #0x80
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, SCRATCH, SCRATCH
|
||||
.set DST_PRELOAD_BIAS, 8
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_cleanup
|
||||
.set DST_PRELOAD_BIAS, 0
|
||||
.unreq HALF
|
||||
.unreq TMP0
|
||||
.unreq TMP1
|
||||
.unreq TMP2
|
||||
.unreq TMP3
|
||||
.unreq WK4
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_combine m, d
|
||||
uxtb16 TMP1, TMP0 /* rb_notmask */
|
||||
uxtb16 TMP2, d /* rb_dest; 1 stall follows */
|
||||
smlatt TMP3, TMP2, TMP1, HALF /* red */
|
||||
smlabb TMP2, TMP2, TMP1, HALF /* blue */
|
||||
uxtb16 TMP0, TMP0, ror #8 /* ag_notmask */
|
||||
uxtb16 TMP1, d, ror #8 /* ag_dest; 1 stall follows */
|
||||
smlatt d, TMP1, TMP0, HALF /* alpha */
|
||||
smlabb TMP1, TMP1, TMP0, HALF /* green */
|
||||
pkhbt TMP0, TMP2, TMP3, lsl #16 /* rb; 1 stall follows */
|
||||
pkhbt TMP1, TMP1, d, lsl #16 /* ag */
|
||||
uxtab16 TMP0, TMP0, TMP0, ror #8
|
||||
uxtab16 TMP1, TMP1, TMP1, ror #8
|
||||
mov TMP0, TMP0, ror #8
|
||||
sel d, TMP0, TMP1
|
||||
uqadd8 d, d, m /* d is a late result */
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_1pixel_head
|
||||
pixld , 4, 1, MASK, 0
|
||||
pixld , 4, 3, DST, 0
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_1pixel_tail
|
||||
mvn TMP0, WK1
|
||||
teq WK1, WK1, asr #32
|
||||
bne 01f
|
||||
bcc 03f
|
||||
mov WK3, WK1
|
||||
b 02f
|
||||
01: over_white_8888_8888_ca_combine WK1, WK3
|
||||
02: pixst , 4, 3, DST
|
||||
03:
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_2pixels_head
|
||||
pixld , 8, 1, MASK, 0
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_2pixels_tail
|
||||
pixld , 8, 3, DST
|
||||
mvn TMP0, WK1
|
||||
teq WK1, WK1, asr #32
|
||||
bne 01f
|
||||
movcs WK3, WK1
|
||||
bcs 02f
|
||||
teq WK2, #0
|
||||
beq 05f
|
||||
b 02f
|
||||
01: over_white_8888_8888_ca_combine WK1, WK3
|
||||
02: mvn TMP0, WK2
|
||||
teq WK2, WK2, asr #32
|
||||
bne 03f
|
||||
movcs WK4, WK2
|
||||
b 04f
|
||||
03: over_white_8888_8888_ca_combine WK2, WK4
|
||||
04: pixst , 8, 3, DST
|
||||
05:
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
.if numbytes == 4
|
||||
over_white_8888_8888_ca_1pixel_head
|
||||
.else
|
||||
.if numbytes == 16
|
||||
over_white_8888_8888_ca_2pixels_head
|
||||
over_white_8888_8888_ca_2pixels_tail
|
||||
.endif
|
||||
over_white_8888_8888_ca_2pixels_head
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro over_white_8888_8888_ca_process_tail cond, numbytes, firstreg
|
||||
.if numbytes == 4
|
||||
over_white_8888_8888_ca_1pixel_tail
|
||||
.else
|
||||
over_white_8888_8888_ca_2pixels_tail
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_over_white_8888_8888_ca_asm_armv6, 0, 32, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH \
|
||||
2, /* prefetch distance */ \
|
||||
over_white_8888_8888_ca_init, \
|
||||
nop_macro, /* newline */ \
|
||||
over_white_8888_8888_ca_cleanup, \
|
||||
over_white_8888_8888_ca_process_head, \
|
||||
over_white_8888_8888_ca_process_tail
|
||||
|
||||
|
||||
.macro over_n_8888_8888_ca_init
|
||||
/* Set up constants. RB_SRC and AG_SRC are in registers;
|
||||
* RB_FLDS, A_SRC, and the two HALF values need to go on the
|
||||
* stack (and the ful SRC value is already there) */
|
||||
ldr SCRATCH, [sp, #ARGS_STACK_OFFSET]
|
||||
mov WK0, #0x00FF0000
|
||||
orr WK0, WK0, #0xFF /* RB_FLDS (0x00FF00FF) */
|
||||
mov WK1, #0x80 /* HALF default value */
|
||||
mov WK2, SCRATCH, lsr #24 /* A_SRC */
|
||||
orr WK3, WK1, WK1, lsl #16 /* HALF alternate value (0x00800080) */
|
||||
push {WK0-WK3}
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET+16
|
||||
uxtb16 SRC, SCRATCH
|
||||
uxtb16 STRIDE_S, SCRATCH, ror #8
|
||||
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, WK3, WK3
|
||||
|
||||
.unreq WK0
|
||||
.unreq WK1
|
||||
.unreq WK2
|
||||
.unreq WK3
|
||||
WK0 .req Y
|
||||
WK1 .req STRIDE_D
|
||||
RB_SRC .req SRC
|
||||
AG_SRC .req STRIDE_S
|
||||
WK2 .req STRIDE_M
|
||||
RB_FLDS .req r8 /* the reloaded constants have to be at consecutive registers starting at an even one */
|
||||
A_SRC .req r8
|
||||
HALF .req r9
|
||||
WK3 .req r10
|
||||
WK4 .req r11
|
||||
WK5 .req SCRATCH
|
||||
WK6 .req ORIG_W
|
||||
|
||||
line_saved_regs Y, STRIDE_D, STRIDE_M, ORIG_W
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_8888_ca_cleanup
|
||||
add sp, sp, #16
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET-16
|
||||
|
||||
.unreq WK0
|
||||
.unreq WK1
|
||||
.unreq RB_SRC
|
||||
.unreq AG_SRC
|
||||
.unreq WK2
|
||||
.unreq RB_FLDS
|
||||
.unreq A_SRC
|
||||
.unreq HALF
|
||||
.unreq WK3
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
WK0 .req r8
|
||||
WK1 .req r9
|
||||
WK2 .req r10
|
||||
WK3 .req r11
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_8888_ca_1pixel_head
|
||||
pixld , 4, 6, MASK, 0
|
||||
pixld , 4, 0, DST, 0
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_8888_ca_1pixel_tail
|
||||
ldrd A_SRC, HALF, [sp, #LOCALS_STACK_OFFSET+8]
|
||||
uxtb16 WK1, WK6 /* rb_mask (first step of hard case placed in what would otherwise be a stall) */
|
||||
teq WK6, WK6, asr #32 /* Zc if transparent, ZC if opaque */
|
||||
bne 20f
|
||||
bcc 40f
|
||||
/* Mask is fully opaque (all channels) */
|
||||
ldr WK6, [sp, #ARGS_STACK_OFFSET] /* get SRC back */
|
||||
eors A_SRC, A_SRC, #0xFF
|
||||
bne 10f
|
||||
/* Source is also opaque - same as src_8888_8888 */
|
||||
mov WK0, WK6
|
||||
b 30f
|
||||
10: /* Same as over_8888_8888 */
|
||||
mul_8888_8 WK0, A_SRC, WK5, HALF
|
||||
uqadd8 WK0, WK0, WK6
|
||||
b 30f
|
||||
20: /* No simplifications possible - do it the hard way */
|
||||
uxtb16 WK2, WK6, ror #8 /* ag_mask */
|
||||
mla WK3, WK1, A_SRC, HALF /* rb_mul; 2 cycles */
|
||||
mla WK4, WK2, A_SRC, HALF /* ag_mul; 2 cycles */
|
||||
ldrd RB_FLDS, HALF, [sp, #LOCALS_STACK_OFFSET]
|
||||
uxtb16 WK5, WK0 /* rb_dest */
|
||||
uxtab16 WK3, WK3, WK3, ror #8
|
||||
uxtb16 WK6, WK0, ror #8 /* ag_dest */
|
||||
uxtab16 WK4, WK4, WK4, ror #8
|
||||
smlatt WK0, RB_SRC, WK1, HALF /* red1 */
|
||||
smlabb WK1, RB_SRC, WK1, HALF /* blue1 */
|
||||
bic WK3, RB_FLDS, WK3, lsr #8
|
||||
bic WK4, RB_FLDS, WK4, lsr #8
|
||||
pkhbt WK1, WK1, WK0, lsl #16 /* rb1 */
|
||||
smlatt WK0, WK5, WK3, HALF /* red2 */
|
||||
smlabb WK3, WK5, WK3, HALF /* blue2 */
|
||||
uxtab16 WK1, WK1, WK1, ror #8
|
||||
smlatt WK5, AG_SRC, WK2, HALF /* alpha1 */
|
||||
pkhbt WK3, WK3, WK0, lsl #16 /* rb2 */
|
||||
smlabb WK0, AG_SRC, WK2, HALF /* green1 */
|
||||
smlatt WK2, WK6, WK4, HALF /* alpha2 */
|
||||
smlabb WK4, WK6, WK4, HALF /* green2 */
|
||||
pkhbt WK0, WK0, WK5, lsl #16 /* ag1 */
|
||||
uxtab16 WK3, WK3, WK3, ror #8
|
||||
pkhbt WK4, WK4, WK2, lsl #16 /* ag2 */
|
||||
uxtab16 WK0, WK0, WK0, ror #8
|
||||
uxtab16 WK4, WK4, WK4, ror #8
|
||||
mov WK1, WK1, ror #8
|
||||
mov WK3, WK3, ror #8
|
||||
sel WK2, WK1, WK0 /* recombine source*mask */
|
||||
sel WK1, WK3, WK4 /* recombine dest*(1-source_alpha*mask) */
|
||||
uqadd8 WK0, WK1, WK2 /* followed by 1 stall */
|
||||
30: /* The destination buffer is already in the L1 cache, so
|
||||
* there's little point in amalgamating writes */
|
||||
pixst , 4, 0, DST
|
||||
40:
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_8888_ca_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
.rept (numbytes / 4) - 1
|
||||
over_n_8888_8888_ca_1pixel_head
|
||||
over_n_8888_8888_ca_1pixel_tail
|
||||
.endr
|
||||
over_n_8888_8888_ca_1pixel_head
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_8888_ca_process_tail cond, numbytes, firstreg
|
||||
over_n_8888_8888_ca_1pixel_tail
|
||||
.endm
|
||||
|
||||
pixman_asm_function pixman_composite_over_n_8888_8888_ca_asm_armv6
|
||||
ldr ip, [sp]
|
||||
cmp ip, #-1
|
||||
beq pixman_composite_over_white_8888_8888_ca_asm_armv6
|
||||
/* else drop through... */
|
||||
.endfunc
|
||||
generate_composite_function \
|
||||
pixman_composite_over_n_8888_8888_ca_asm_armv6_helper, 0, 32, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH | FLAG_PROCESS_CORRUPTS_WK0 \
|
||||
2, /* prefetch distance */ \
|
||||
over_n_8888_8888_ca_init, \
|
||||
nop_macro, /* newline */ \
|
||||
over_n_8888_8888_ca_cleanup, \
|
||||
over_n_8888_8888_ca_process_head, \
|
||||
over_n_8888_8888_ca_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro in_reverse_8888_8888_init
|
||||
/* Hold loop invariant in MASK */
|
||||
ldr MASK, =0x00800080
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, MASK, MASK
|
||||
/* Offset the source pointer: we only need the alpha bytes */
|
||||
add SRC, SRC, #3
|
||||
line_saved_regs ORIG_W
|
||||
.endm
|
||||
|
||||
.macro in_reverse_8888_8888_head numbytes, reg1, reg2, reg3
|
||||
ldrb ORIG_W, [SRC], #4
|
||||
.if numbytes >= 8
|
||||
ldrb WK®1, [SRC], #4
|
||||
.if numbytes == 16
|
||||
ldrb WK®2, [SRC], #4
|
||||
ldrb WK®3, [SRC], #4
|
||||
.endif
|
||||
.endif
|
||||
add DST, DST, #numbytes
|
||||
.endm
|
||||
|
||||
.macro in_reverse_8888_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
in_reverse_8888_8888_head numbytes, firstreg, %(firstreg+1), %(firstreg+2)
|
||||
.endm
|
||||
|
||||
.macro in_reverse_8888_8888_1pixel s, d, offset, is_only
|
||||
.if is_only != 1
|
||||
movs s, ORIG_W
|
||||
.if offset != 0
|
||||
ldrb ORIG_W, [SRC, #offset]
|
||||
.endif
|
||||
beq 01f
|
||||
teq STRIDE_M, #0xFF
|
||||
beq 02f
|
||||
.endif
|
||||
uxtb16 SCRATCH, d /* rb_dest */
|
||||
uxtb16 d, d, ror #8 /* ag_dest */
|
||||
mla SCRATCH, SCRATCH, s, MASK
|
||||
mla d, d, s, MASK
|
||||
uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8
|
||||
uxtab16 d, d, d, ror #8
|
||||
mov SCRATCH, SCRATCH, ror #8
|
||||
sel d, SCRATCH, d
|
||||
b 02f
|
||||
.if offset == 0
|
||||
48: /* Last mov d,#0 of the set - used as part of shortcut for
|
||||
* source values all 0 */
|
||||
.endif
|
||||
01: mov d, #0
|
||||
02:
|
||||
.endm
|
||||
|
||||
.macro in_reverse_8888_8888_tail numbytes, reg1, reg2, reg3, reg4
|
||||
.if numbytes == 4
|
||||
teq ORIG_W, ORIG_W, asr #32
|
||||
ldrne WK®1, [DST, #-4]
|
||||
.elseif numbytes == 8
|
||||
teq ORIG_W, WK®1
|
||||
teqeq ORIG_W, ORIG_W, asr #32 /* all 0 or all -1? */
|
||||
ldmnedb DST, {WK®1-WK®2}
|
||||
.else
|
||||
teq ORIG_W, WK®1
|
||||
teqeq ORIG_W, WK®2
|
||||
teqeq ORIG_W, WK®3
|
||||
teqeq ORIG_W, ORIG_W, asr #32 /* all 0 or all -1? */
|
||||
ldmnedb DST, {WK®1-WK®4}
|
||||
.endif
|
||||
cmnne DST, #0 /* clear C if NE */
|
||||
bcs 49f /* no writes to dest if source all -1 */
|
||||
beq 48f /* set dest to all 0 if source all 0 */
|
||||
.if numbytes == 4
|
||||
in_reverse_8888_8888_1pixel ORIG_W, WK®1, 0, 1
|
||||
str WK®1, [DST, #-4]
|
||||
.elseif numbytes == 8
|
||||
in_reverse_8888_8888_1pixel STRIDE_M, WK®1, -4, 0
|
||||
in_reverse_8888_8888_1pixel STRIDE_M, WK®2, 0, 0
|
||||
stmdb DST, {WK®1-WK®2}
|
||||
.else
|
||||
in_reverse_8888_8888_1pixel STRIDE_M, WK®1, -12, 0
|
||||
in_reverse_8888_8888_1pixel STRIDE_M, WK®2, -8, 0
|
||||
in_reverse_8888_8888_1pixel STRIDE_M, WK®3, -4, 0
|
||||
in_reverse_8888_8888_1pixel STRIDE_M, WK®4, 0, 0
|
||||
stmdb DST, {WK®1-WK®4}
|
||||
.endif
|
||||
49:
|
||||
.endm
|
||||
|
||||
.macro in_reverse_8888_8888_process_tail cond, numbytes, firstreg
|
||||
in_reverse_8888_8888_tail numbytes, firstreg, %(firstreg+1), %(firstreg+2), %(firstreg+3)
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_in_reverse_8888_8888_asm_armv6, 32, 0, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH | FLAG_NO_PRELOAD_DST \
|
||||
2, /* prefetch distance */ \
|
||||
in_reverse_8888_8888_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
in_reverse_8888_8888_process_head, \
|
||||
in_reverse_8888_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro over_n_8888_init
|
||||
ldr SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
/* Hold loop invariant in MASK */
|
||||
ldr MASK, =0x00800080
|
||||
/* Hold multiplier for destination in STRIDE_M */
|
||||
mov STRIDE_M, #255
|
||||
sub STRIDE_M, STRIDE_M, SRC, lsr #24
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
uadd8 SCRATCH, MASK, MASK
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
pixld , numbytes, firstreg, DST, 0
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_1pixel dst
|
||||
mul_8888_8 WK&dst, STRIDE_M, SCRATCH, MASK
|
||||
uqadd8 WK&dst, WK&dst, SRC
|
||||
.endm
|
||||
|
||||
.macro over_n_8888_process_tail cond, numbytes, firstreg
|
||||
.set PROCESS_REG, firstreg
|
||||
.rept numbytes / 4
|
||||
over_n_8888_1pixel %(PROCESS_REG)
|
||||
.set PROCESS_REG, PROCESS_REG+1
|
||||
.endr
|
||||
pixst , numbytes, firstreg, DST
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
pixman_composite_over_n_8888_asm_armv6, 0, 0, 32 \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_DOES_STORE \
|
||||
2, /* prefetch distance */ \
|
||||
over_n_8888_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
over_n_8888_process_head, \
|
||||
over_n_8888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
|||
|
|
@ -76,6 +76,16 @@
|
|||
.set FLAG_SPILL_LINE_VARS, 48
|
||||
.set FLAG_PROCESS_CORRUPTS_SCRATCH, 0
|
||||
.set FLAG_PROCESS_PRESERVES_SCRATCH, 64
|
||||
.set FLAG_PROCESS_PRESERVES_WK0, 0
|
||||
.set FLAG_PROCESS_CORRUPTS_WK0, 128 /* if possible, use the specified register(s) instead so WK0 can hold number of leading pixels */
|
||||
.set FLAG_PRELOAD_DST, 0
|
||||
.set FLAG_NO_PRELOAD_DST, 256
|
||||
|
||||
/*
|
||||
* Number of bytes by which to adjust preload offset of destination
|
||||
* buffer (allows preload instruction to be moved before the load(s))
|
||||
*/
|
||||
.set DST_PRELOAD_BIAS, 0
|
||||
|
||||
/*
|
||||
* Offset into stack where mask and source pointer/stride can be accessed.
|
||||
|
|
@ -86,6 +96,11 @@
|
|||
.set ARGS_STACK_OFFSET, (9*4)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Offset into stack where space allocated during init macro can be accessed.
|
||||
*/
|
||||
.set LOCALS_STACK_OFFSET, 0
|
||||
|
||||
/*
|
||||
* Constants for selecting preferable prefetch type.
|
||||
*/
|
||||
|
|
@ -196,8 +211,8 @@
|
|||
PF add, SCRATCH, base, WK0, lsl #bpp_shift-dst_bpp_shift
|
||||
PF and, SCRATCH, SCRATCH, #31
|
||||
PF rsb, SCRATCH, SCRATCH, WK0, lsl #bpp_shift-dst_bpp_shift
|
||||
PF sub, SCRATCH, SCRATCH, #1 /* so now ranges are -16..-1 / 0..31 / 32..63 */
|
||||
PF movs, SCRATCH, SCRATCH, #32-6 /* so this sets NC / nc / Nc */
|
||||
PF sub, SCRATCH, SCRATCH, #1 /* so now ranges are -16..-1 / 0..31 / 32..63 */
|
||||
PF movs, SCRATCH, SCRATCH, lsl #32-6 /* so this sets NC / nc / Nc */
|
||||
PF bcs, 61f
|
||||
PF bpl, 60f
|
||||
PF pld, [ptr, #32*(prefetch_distance+2)]
|
||||
|
|
@ -359,23 +374,41 @@
|
|||
|
||||
|
||||
.macro test_bits_1_0_ptr
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
|
||||
movs SCRATCH, X, lsl #32-1 /* C,N = bits 1,0 of DST */
|
||||
.else
|
||||
movs SCRATCH, WK0, lsl #32-1 /* C,N = bits 1,0 of DST */
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro test_bits_3_2_ptr
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
|
||||
movs SCRATCH, X, lsl #32-3 /* C,N = bits 3, 2 of DST */
|
||||
.else
|
||||
movs SCRATCH, WK0, lsl #32-3 /* C,N = bits 3, 2 of DST */
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro leading_15bytes process_head, process_tail
|
||||
/* On entry, WK0 bits 0-3 = number of bytes until destination is 16-byte aligned */
|
||||
.set DECREMENT_X, 1
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
|
||||
.set DECREMENT_X, 0
|
||||
sub X, X, WK0, lsr #dst_bpp_shift
|
||||
str X, [sp, #LINE_SAVED_REG_COUNT*4]
|
||||
mov X, WK0
|
||||
.endif
|
||||
/* Use unaligned loads in all cases for simplicity */
|
||||
.if dst_w_bpp == 8
|
||||
conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, 1
|
||||
conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X
|
||||
.elseif dst_w_bpp == 16
|
||||
test_bits_1_0_ptr
|
||||
conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, 1
|
||||
conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, DECREMENT_X
|
||||
.endif
|
||||
conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
|
||||
ldr X, [sp, #LINE_SAVED_REG_COUNT*4]
|
||||
.endif
|
||||
conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, 1
|
||||
.endm
|
||||
|
||||
.macro test_bits_3_2_pix
|
||||
|
|
@ -414,7 +447,7 @@
|
|||
preload_middle src_bpp, SRC, 0
|
||||
preload_middle mask_bpp, MASK, 0
|
||||
.endif
|
||||
.if (dst_r_bpp > 0) && ((SUBBLOCK % 2) == 0)
|
||||
.if (dst_r_bpp > 0) && ((SUBBLOCK % 2) == 0) && (((flags) & FLAG_NO_PRELOAD_DST) == 0)
|
||||
/* Because we know that writes are 16-byte aligned, it's relatively easy to ensure that
|
||||
* destination prefetches are 32-byte aligned. It's also the easiest channel to offset
|
||||
* preloads for, to achieve staggered prefetches for multiple channels, because there are
|
||||
|
|
@ -437,11 +470,11 @@
|
|||
.if dst_r_bpp > 0
|
||||
tst DST, #16
|
||||
bne 111f
|
||||
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 16
|
||||
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 16 + DST_PRELOAD_BIAS
|
||||
b 112f
|
||||
111:
|
||||
.endif
|
||||
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 0
|
||||
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 0 + DST_PRELOAD_BIAS
|
||||
112:
|
||||
/* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */
|
||||
.if (src_bpp*pix_per_block > 256) || (mask_bpp*pix_per_block > 256) || (dst_r_bpp*pix_per_block > 256)
|
||||
|
|
@ -449,7 +482,9 @@
|
|||
.endif
|
||||
preload_trailing src_bpp, src_bpp_shift, SRC
|
||||
preload_trailing mask_bpp, mask_bpp_shift, MASK
|
||||
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
|
||||
preload_trailing dst_r_bpp, dst_bpp_shift, DST
|
||||
.endif
|
||||
add X, X, #(prefetch_distance+2)*pix_per_block - 128/dst_w_bpp
|
||||
/* The remainder of the line is handled identically to the medium case */
|
||||
medium_case_inner_loop_and_trailing_pixels process_head, process_tail,, exit_label, unaligned_src, unaligned_mask
|
||||
|
|
@ -561,13 +596,7 @@
|
|||
process_tail, \
|
||||
process_inner_loop
|
||||
|
||||
.func fname
|
||||
.global fname
|
||||
/* For ELF format also set function visibility to hidden */
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
pixman_asm_function fname
|
||||
|
||||
/*
|
||||
* Make some macro arguments globally visible and accessible
|
||||
|
|
@ -679,16 +708,12 @@
|
|||
SCRATCH .req r12
|
||||
ORIG_W .req r14 /* width (pixels) */
|
||||
|
||||
fname:
|
||||
.fnstart
|
||||
.save {r4-r11, lr}
|
||||
push {r4-r11, lr} /* save all registers */
|
||||
|
||||
subs Y, Y, #1
|
||||
blo 199f
|
||||
|
||||
#ifdef DEBUG_PARAMS
|
||||
.pad #9*4
|
||||
sub sp, sp, #9*4
|
||||
#endif
|
||||
|
||||
|
|
@ -708,6 +733,13 @@ fname:
|
|||
#endif
|
||||
|
||||
init
|
||||
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
|
||||
/* Reserve a word in which to store X during leading pixels */
|
||||
sub sp, sp, #4
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET+4
|
||||
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET+4
|
||||
.endif
|
||||
|
||||
lsl STRIDE_D, #dst_bpp_shift /* stride in bytes */
|
||||
sub STRIDE_D, STRIDE_D, X, lsl #dst_bpp_shift
|
||||
|
|
@ -737,42 +769,49 @@ fname:
|
|||
.if (flags) & FLAG_SPILL_LINE_VARS_WIDE
|
||||
/* This is stmdb sp!,{} */
|
||||
.word 0xE92D0000 | LINE_SAVED_REGS
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
|
||||
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
|
||||
.endif
|
||||
151: /* New line */
|
||||
newline
|
||||
preload_leading_step1 src_bpp, WK1, SRC
|
||||
preload_leading_step1 mask_bpp, WK2, MASK
|
||||
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
|
||||
preload_leading_step1 dst_r_bpp, WK3, DST
|
||||
|
||||
tst DST, #15
|
||||
beq 154f
|
||||
rsb WK0, DST, #0 /* bits 0-3 = number of leading bytes until destination aligned */
|
||||
.if (src_bpp != 0 && src_bpp != 2*dst_w_bpp) || (mask_bpp != 0 && mask_bpp != 2*dst_w_bpp)
|
||||
PF and, WK0, WK0, #15
|
||||
.endif
|
||||
|
||||
ands WK0, DST, #15
|
||||
beq 154f
|
||||
rsb WK0, WK0, #16 /* number of leading bytes until destination aligned */
|
||||
|
||||
preload_leading_step2 src_bpp, src_bpp_shift, WK1, SRC
|
||||
preload_leading_step2 mask_bpp, mask_bpp_shift, WK2, MASK
|
||||
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
|
||||
preload_leading_step2 dst_r_bpp, dst_bpp_shift, WK3, DST
|
||||
.endif
|
||||
|
||||
leading_15bytes process_head, process_tail
|
||||
|
||||
154: /* Destination now 16-byte aligned; we have at least one prefetch on each channel as well as at least one 16-byte output block */
|
||||
.if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
.if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
and SCRATCH, SRC, #31
|
||||
rsb SCRATCH, SCRATCH, #32*prefetch_distance
|
||||
.elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
.elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
|
||||
and SCRATCH, MASK, #31
|
||||
rsb SCRATCH, SCRATCH, #32*prefetch_distance
|
||||
.endif
|
||||
.ifc "process_inner_loop",""
|
||||
.endif
|
||||
.ifc "process_inner_loop",""
|
||||
switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, wide_case_inner_loop, 157f
|
||||
.else
|
||||
.else
|
||||
switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, process_inner_loop, 157f
|
||||
.endif
|
||||
.endif
|
||||
|
||||
157: /* Check for another line */
|
||||
end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_WIDE), 151b
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS_WIDE
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
|
||||
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.ltorg
|
||||
|
|
@ -782,17 +821,21 @@ fname:
|
|||
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
|
||||
/* This is stmdb sp!,{} */
|
||||
.word 0xE92D0000 | LINE_SAVED_REGS
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
|
||||
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
|
||||
.endif
|
||||
161: /* New line */
|
||||
newline
|
||||
preload_line 0, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */
|
||||
preload_line 0, mask_bpp, mask_bpp_shift, MASK
|
||||
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
|
||||
preload_line 0, dst_r_bpp, dst_bpp_shift, DST
|
||||
.endif
|
||||
|
||||
sub X, X, #128/dst_w_bpp /* simplifies inner loop termination */
|
||||
tst DST, #15
|
||||
ands WK0, DST, #15
|
||||
beq 164f
|
||||
rsb WK0, DST, #0 /* bits 0-3 = number of leading bytes until destination aligned */
|
||||
rsb WK0, WK0, #16 /* number of leading bytes until destination aligned */
|
||||
|
||||
leading_15bytes process_head, process_tail
|
||||
|
||||
|
|
@ -816,7 +859,9 @@ fname:
|
|||
newline
|
||||
preload_line 1, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */
|
||||
preload_line 1, mask_bpp, mask_bpp_shift, MASK
|
||||
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
|
||||
preload_line 1, dst_r_bpp, dst_bpp_shift, DST
|
||||
.endif
|
||||
|
||||
.if dst_w_bpp == 8
|
||||
tst DST, #3
|
||||
|
|
@ -847,12 +892,22 @@ fname:
|
|||
|
||||
177: /* Check for another line */
|
||||
end_of_line %(dst_w_bpp < 32), %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 171b, last_one
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
|
||||
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
|
||||
.endif
|
||||
|
||||
197:
|
||||
.if (flags) & FLAG_SPILL_LINE_VARS
|
||||
add sp, sp, #LINE_SAVED_REG_COUNT*4
|
||||
.endif
|
||||
198:
|
||||
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
|
||||
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET-4
|
||||
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET-4
|
||||
add sp, sp, #4
|
||||
.endif
|
||||
|
||||
cleanup
|
||||
|
||||
#ifdef DEBUG_PARAMS
|
||||
|
|
@ -860,7 +915,6 @@ fname:
|
|||
#endif
|
||||
199:
|
||||
pop {r4-r11, pc} /* exit */
|
||||
.fnend
|
||||
|
||||
.ltorg
|
||||
|
||||
|
|
|
|||
|
|
@ -41,11 +41,20 @@ PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_8_8,
|
|||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_0565_8888,
|
||||
uint16_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_x888_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, add_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, over_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, in_reverse_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, armv6, over_n_8888,
|
||||
uint32_t, 1)
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_DST (0, armv6, over_reverse_n_8888,
|
||||
uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, armv6, over_8888_n_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
|
@ -53,6 +62,9 @@ PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, armv6, over_8888_n_8888,
|
|||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8888_8888_ca,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 0565_0565, SRC,
|
||||
uint16_t, uint16_t)
|
||||
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 8888_8888, SRC,
|
||||
|
|
@ -216,6 +228,11 @@ static const pixman_fast_path_t arm_simd_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, armv6_composite_src_0565_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, armv6_composite_src_0565_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, armv6_composite_src_x888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, armv6_composite_src_x888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, armv6_composite_src_x888_0565),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, armv6_composite_src_x888_0565),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, armv6_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, armv6_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, armv6_composite_over_8888_8888),
|
||||
|
|
@ -225,6 +242,13 @@ static const pixman_fast_path_t arm_simd_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, armv6_composite_over_8888_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, armv6_composite_over_8888_n_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, armv6_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, armv6_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8b8g8r8, armv6_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8b8g8r8, armv6_composite_over_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, armv6_composite_over_reverse_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, armv6_composite_over_reverse_n_8888),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, armv6_composite_add_8_8),
|
||||
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, armv6_composite_over_n_8_8888),
|
||||
|
|
@ -232,15 +256,25 @@ static const pixman_fast_path_t arm_simd_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, armv6_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, armv6_composite_over_n_8_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, armv6_0565_0565),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, b5g6r5, armv6_0565_0565),
|
||||
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8r8g8b8, null, a8r8g8b8, armv6_composite_in_reverse_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8r8g8b8, null, x8r8g8b8, armv6_composite_in_reverse_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8b8g8r8, null, a8b8g8r8, armv6_composite_in_reverse_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8b8g8r8, null, x8b8g8r8, armv6_composite_in_reverse_8888_8888),
|
||||
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, armv6_8888_8888),
|
||||
PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, armv6_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, armv6_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, armv6_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, armv6_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, armv6_composite_over_n_8888_8888_ca),
|
||||
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, armv6_0565_0565),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, b5g6r5, armv6_0565_0565),
|
||||
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, armv6_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, armv6_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, armv6_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, armv6_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, armv6_8888_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, armv6_8888_8888),
|
||||
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2021 Moonchild Productions
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the names of the authors not be used in advertising or
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The authors make no representations about the
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
|
|
@ -95,6 +94,35 @@ detect_cpu_features (void)
|
|||
return features;
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__) || defined(ANDROID) /* Android */
|
||||
|
||||
#include <cpu-features.h>
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
AndroidCpuFamily cpu_family;
|
||||
uint64_t cpu_features;
|
||||
|
||||
cpu_family = android_getCpuFamily();
|
||||
cpu_features = android_getCpuFeatures();
|
||||
|
||||
if (cpu_family == ANDROID_CPU_FAMILY_ARM)
|
||||
{
|
||||
if (cpu_features & ANDROID_CPU_ARM_FEATURE_ARMv7)
|
||||
features |= ARM_V7;
|
||||
|
||||
if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3)
|
||||
features |= ARM_VFP;
|
||||
|
||||
if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)
|
||||
features |= ARM_NEON;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#elif defined (__linux__) /* linux ELF */
|
||||
|
||||
#include <unistd.h>
|
||||
|
|
@ -148,6 +176,31 @@ detect_cpu_features (void)
|
|||
return features;
|
||||
}
|
||||
|
||||
#elif defined (_3DS) /* 3DS homebrew (devkitARM) */
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
|
||||
features |= ARM_V6;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#elif defined (PSP2) || defined (__SWITCH__)
|
||||
/* Vita (VitaSDK) or Switch (devkitA64) homebrew */
|
||||
|
||||
static arm_cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
arm_cpu_features_t features = 0;
|
||||
|
||||
features |= ARM_NEON;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#else /* Unknown */
|
||||
|
||||
static arm_cpu_features_t
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -42,8 +42,6 @@
|
|||
#define force_inline __inline__
|
||||
#endif
|
||||
|
||||
#define IS_ZERO(f) (-FLT_MIN < (f) && (f) < FLT_MIN)
|
||||
|
||||
typedef float (* combine_channel_t) (float sa, float s, float da, float d);
|
||||
|
||||
static force_inline void
|
||||
|
|
@ -203,56 +201,56 @@ get_factor (combine_factor_t factor, float sa, float da)
|
|||
break;
|
||||
|
||||
case SA_OVER_DA:
|
||||
if (IS_ZERO (da))
|
||||
if (FLOAT_IS_ZERO (da))
|
||||
f = 1.0f;
|
||||
else
|
||||
f = CLAMP (sa / da);
|
||||
break;
|
||||
|
||||
case DA_OVER_SA:
|
||||
if (IS_ZERO (sa))
|
||||
if (FLOAT_IS_ZERO (sa))
|
||||
f = 1.0f;
|
||||
else
|
||||
f = CLAMP (da / sa);
|
||||
break;
|
||||
|
||||
case INV_SA_OVER_DA:
|
||||
if (IS_ZERO (da))
|
||||
if (FLOAT_IS_ZERO (da))
|
||||
f = 1.0f;
|
||||
else
|
||||
f = CLAMP ((1.0f - sa) / da);
|
||||
break;
|
||||
|
||||
case INV_DA_OVER_SA:
|
||||
if (IS_ZERO (sa))
|
||||
if (FLOAT_IS_ZERO (sa))
|
||||
f = 1.0f;
|
||||
else
|
||||
f = CLAMP ((1.0f - da) / sa);
|
||||
break;
|
||||
|
||||
case ONE_MINUS_SA_OVER_DA:
|
||||
if (IS_ZERO (da))
|
||||
if (FLOAT_IS_ZERO (da))
|
||||
f = 0.0f;
|
||||
else
|
||||
f = CLAMP (1.0f - sa / da);
|
||||
break;
|
||||
|
||||
case ONE_MINUS_DA_OVER_SA:
|
||||
if (IS_ZERO (sa))
|
||||
if (FLOAT_IS_ZERO (sa))
|
||||
f = 0.0f;
|
||||
else
|
||||
f = CLAMP (1.0f - da / sa);
|
||||
break;
|
||||
|
||||
case ONE_MINUS_INV_DA_OVER_SA:
|
||||
if (IS_ZERO (sa))
|
||||
if (FLOAT_IS_ZERO (sa))
|
||||
f = 0.0f;
|
||||
else
|
||||
f = CLAMP (1.0f - (1.0f - da) / sa);
|
||||
break;
|
||||
|
||||
case ONE_MINUS_INV_SA_OVER_DA:
|
||||
if (IS_ZERO (da))
|
||||
if (FLOAT_IS_ZERO (da))
|
||||
f = 0.0f;
|
||||
else
|
||||
f = CLAMP (1.0f - (1.0f - sa) / da);
|
||||
|
|
@ -321,23 +319,44 @@ MAKE_PD_COMBINERS (conjoint_xor, ONE_MINUS_DA_OVER_SA, ONE_MINUS_SA_OVER_DA)
|
|||
*
|
||||
* The following blend modes have been taken from the PDF ISO 32000
|
||||
* specification, which at this point in time is available from
|
||||
* http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
|
||||
* The relevant chapters are 11.3.5 and 11.3.6.
|
||||
*
|
||||
* http://www.adobe.com/devnet/pdf/pdf_reference.html
|
||||
*
|
||||
* The specific documents of interest are the PDF spec itself:
|
||||
*
|
||||
* http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf
|
||||
*
|
||||
* chapters 11.3.5 and 11.3.6 and a later supplement for Adobe Acrobat
|
||||
* 9.1 and Reader 9.1:
|
||||
*
|
||||
* http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf
|
||||
*
|
||||
* that clarifies the specifications for blend modes ColorDodge and
|
||||
* ColorBurn.
|
||||
*
|
||||
* The formula for computing the final pixel color given in 11.3.6 is:
|
||||
* αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
|
||||
* with B() being the blend function.
|
||||
* Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
|
||||
*
|
||||
* These blend modes should match the SVG filter draft specification, as
|
||||
* it has been designed to mirror ISO 32000. Note that at the current point
|
||||
* no released draft exists that shows this, as the formulas have not been
|
||||
* updated yet after the release of ISO 32000.
|
||||
* αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
|
||||
*
|
||||
* The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
|
||||
* PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
|
||||
* argument. Note that this implementation operates on premultiplied colors,
|
||||
* while the PDF specification does not. Therefore the code uses the formula
|
||||
* ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
|
||||
* with B() is the blend function. When B(Cb, Cs) = Cs, this formula
|
||||
* reduces to the regular OVER operator.
|
||||
*
|
||||
* Cs and Cb are not premultiplied, so in our implementation we instead
|
||||
* use:
|
||||
*
|
||||
* cr = (1 – αs) × cb + (1 – αb) × cs + αb × αs × B (cb/αb, cs/αs)
|
||||
*
|
||||
* where cr, cs, and cb are premultiplied colors, and where the
|
||||
*
|
||||
* αb × αs × B(cb/αb, cs/αs)
|
||||
*
|
||||
* part is first arithmetically simplified under the assumption that αb
|
||||
* and αs are not 0, and then updated to produce a meaningful result when
|
||||
* they are.
|
||||
*
|
||||
* For all the blend mode operators, the alpha channel is given by
|
||||
*
|
||||
* αr = αs + αb + αb × αs
|
||||
*/
|
||||
|
||||
#define MAKE_SEPARABLE_PDF_COMBINERS(name) \
|
||||
|
|
@ -357,18 +376,55 @@ MAKE_PD_COMBINERS (conjoint_xor, ONE_MINUS_DA_OVER_SA, ONE_MINUS_SA_OVER_DA)
|
|||
\
|
||||
MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
|
||||
|
||||
/*
|
||||
* Multiply
|
||||
*
|
||||
* ad * as * B(d / ad, s / as)
|
||||
* = ad * as * d/ad * s/as
|
||||
* = d * s
|
||||
*
|
||||
*/
|
||||
static force_inline float
|
||||
blend_multiply (float sa, float s, float da, float d)
|
||||
{
|
||||
return d * s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Screen
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = ad * as * (d/ad + s/as - s/as * d/ad)
|
||||
* = ad * s + as * d - s * d
|
||||
*/
|
||||
static force_inline float
|
||||
blend_screen (float sa, float s, float da, float d)
|
||||
{
|
||||
return d * sa + s * da - s * d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overlay
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = ad * as * Hardlight (s, d)
|
||||
* = if (d / ad < 0.5)
|
||||
* as * ad * Multiply (s/as, 2 * d/ad)
|
||||
* else
|
||||
* as * ad * Screen (s/as, 2 * d / ad - 1)
|
||||
* = if (d < 0.5 * ad)
|
||||
* as * ad * s/as * 2 * d /ad
|
||||
* else
|
||||
* as * ad * (s/as + 2 * d / ad - 1 - s / as * (2 * d / ad - 1))
|
||||
* = if (2 * d < ad)
|
||||
* 2 * s * d
|
||||
* else
|
||||
* ad * s + 2 * as * d - as * ad - ad * s * (2 * d / ad - 1)
|
||||
* = if (2 * d < ad)
|
||||
* 2 * s * d
|
||||
* else
|
||||
* as * ad - 2 * (ad - d) * (as - s)
|
||||
*/
|
||||
static force_inline float
|
||||
blend_overlay (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -378,6 +434,13 @@ blend_overlay (float sa, float s, float da, float d)
|
|||
return sa * da - 2 * (da - d) * (sa - s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Darken
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = ad * as * MIN(d/ad, s/as)
|
||||
* = MIN (as * d, ad * s)
|
||||
*/
|
||||
static force_inline float
|
||||
blend_darken (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -390,6 +453,13 @@ blend_darken (float sa, float s, float da, float d)
|
|||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lighten
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = ad * as * MAX(d/ad, s/as)
|
||||
* = MAX (as * d, ad * s)
|
||||
*/
|
||||
static force_inline float
|
||||
blend_lighten (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -402,19 +472,57 @@ blend_lighten (float sa, float s, float da, float d)
|
|||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Color dodge
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = if d/ad = 0
|
||||
* ad * as * 0
|
||||
* else if (d/ad >= (1 - s/as)
|
||||
* ad * as * 1
|
||||
* else
|
||||
* ad * as * ((d/ad) / (1 - s/as))
|
||||
* = if d = 0
|
||||
* 0
|
||||
* elif as * d >= ad * (as - s)
|
||||
* ad * as
|
||||
* else
|
||||
* as * (as * d / (as - s))
|
||||
*
|
||||
*/
|
||||
static force_inline float
|
||||
blend_color_dodge (float sa, float s, float da, float d)
|
||||
{
|
||||
if (IS_ZERO (d))
|
||||
if (FLOAT_IS_ZERO (d))
|
||||
return 0.0f;
|
||||
else if (d * sa >= sa * da - s * da)
|
||||
return sa * da;
|
||||
else if (IS_ZERO (sa - s))
|
||||
else if (FLOAT_IS_ZERO (sa - s))
|
||||
return sa * da;
|
||||
else
|
||||
return sa * sa * d / (sa - s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Color burn
|
||||
*
|
||||
* We modify the first clause "if d = 1" to "if d >= 1" since with
|
||||
* premultiplied colors d > 1 can actually happen.
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = if d/ad >= 1
|
||||
* ad * as * 1
|
||||
* elif (1 - d/ad) >= s/as
|
||||
* ad * as * 0
|
||||
* else
|
||||
* ad * as * (1 - ((1 - d/ad) / (s/as)))
|
||||
* = if d >= ad
|
||||
* ad * as
|
||||
* elif as * ad - as * d >= ad * s
|
||||
* 0
|
||||
* else
|
||||
* ad * as - as * as * (ad - d) / s
|
||||
*/
|
||||
static force_inline float
|
||||
blend_color_burn (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -422,12 +530,29 @@ blend_color_burn (float sa, float s, float da, float d)
|
|||
return sa * da;
|
||||
else if (sa * (da - d) >= s * da)
|
||||
return 0.0f;
|
||||
else if (IS_ZERO (s))
|
||||
else if (FLOAT_IS_ZERO (s))
|
||||
return 0.0f;
|
||||
else
|
||||
return sa * (da - sa * (da - d) / s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hard light
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = if (s/as <= 0.5)
|
||||
* ad * as * Multiply (d/ad, 2 * s/as)
|
||||
* else
|
||||
* ad * as * Screen (d/ad, 2 * s/as - 1)
|
||||
* = if 2 * s <= as
|
||||
* ad * as * d/ad * 2 * s / as
|
||||
* else
|
||||
* ad * as * (d/ad + (2 * s/as - 1) + d/ad * (2 * s/as - 1))
|
||||
* = if 2 * s <= as
|
||||
* 2 * s * d
|
||||
* else
|
||||
* as * ad - 2 * (ad - d) * (as - s)
|
||||
*/
|
||||
static force_inline float
|
||||
blend_hard_light (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -437,21 +562,38 @@ blend_hard_light (float sa, float s, float da, float d)
|
|||
return sa * da - 2 * (da - d) * (sa - s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Soft light
|
||||
*
|
||||
* ad * as * B(d/ad, s/as)
|
||||
* = if (s/as <= 0.5)
|
||||
* ad * as * (d/ad - (1 - 2 * s/as) * d/ad * (1 - d/ad))
|
||||
* else if (d/ad <= 0.25)
|
||||
* ad * as * (d/ad + (2 * s/as - 1) * ((((16 * d/ad - 12) * d/ad + 4) * d/ad) - d/ad))
|
||||
* else
|
||||
* ad * as * (d/ad + (2 * s/as - 1) * sqrt (d/ad))
|
||||
* = if (2 * s <= as)
|
||||
* d * as - d * (ad - d) * (as - 2 * s) / ad;
|
||||
* else if (4 * d <= ad)
|
||||
* (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
|
||||
* else
|
||||
* d * as + (sqrt (d * ad) - d) * (2 * s - as);
|
||||
*/
|
||||
static force_inline float
|
||||
blend_soft_light (float sa, float s, float da, float d)
|
||||
{
|
||||
if (2 * s < sa)
|
||||
if (2 * s <= sa)
|
||||
{
|
||||
if (IS_ZERO (da))
|
||||
if (FLOAT_IS_ZERO (da))
|
||||
return d * sa;
|
||||
else
|
||||
return d * sa - d * (da - d) * (sa - 2 * s) / da;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_ZERO (da))
|
||||
if (FLOAT_IS_ZERO (da))
|
||||
{
|
||||
return 0.0f;
|
||||
return d * sa;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -463,6 +605,20 @@ blend_soft_light (float sa, float s, float da, float d)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Difference
|
||||
*
|
||||
* ad * as * B(s/as, d/ad)
|
||||
* = ad * as * abs (s/as - d/ad)
|
||||
* = if (s/as <= d/ad)
|
||||
* ad * as * (d/ad - s/as)
|
||||
* else
|
||||
* ad * as * (s/as - d/ad)
|
||||
* = if (ad * s <= as * d)
|
||||
* as * d - ad * s
|
||||
* else
|
||||
* ad * s - as * d
|
||||
*/
|
||||
static force_inline float
|
||||
blend_difference (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -475,6 +631,13 @@ blend_difference (float sa, float s, float da, float d)
|
|||
return sda - dsa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exclusion
|
||||
*
|
||||
* ad * as * B(s/as, d/ad)
|
||||
* = ad * as * (d/ad + s/as - 2 * d/ad * s/as)
|
||||
* = as * d + ad * s - 2 * s * d
|
||||
*/
|
||||
static force_inline float
|
||||
blend_exclusion (float sa, float s, float da, float d)
|
||||
{
|
||||
|
|
@ -494,116 +657,79 @@ MAKE_SEPARABLE_PDF_COMBINERS (difference)
|
|||
MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
|
||||
|
||||
/*
|
||||
* PDF nonseperable blend modes.
|
||||
*
|
||||
* These are implemented using the following functions to operate in Hsl
|
||||
* space, with Cmax, Cmid, Cmin referring to the max, mid and min value
|
||||
* of the red, green and blue components.
|
||||
* PDF nonseperable blend modes are implemented using the following functions
|
||||
* to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
|
||||
* and min value of the red, green and blue components.
|
||||
*
|
||||
* LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
|
||||
*
|
||||
* clip_color (C):
|
||||
* l = LUM (C)
|
||||
* min = Cmin
|
||||
* max = Cmax
|
||||
* if n < 0.0
|
||||
* C = l + (((C – l) × l) ⁄ (l – min))
|
||||
* if x > 1.0
|
||||
* C = l + (((C – l) × (1 – l)) (max – l))
|
||||
* return C
|
||||
* l = LUM (C)
|
||||
* min = Cmin
|
||||
* max = Cmax
|
||||
* if n < 0.0
|
||||
* C = l + (((C – l) × l) ⁄ (l – min))
|
||||
* if x > 1.0
|
||||
* C = l + (((C – l) × (1 – l) ) ⁄ (max – l))
|
||||
* return C
|
||||
*
|
||||
* set_lum (C, l):
|
||||
* d = l – LUM (C)
|
||||
* C += d
|
||||
* return clip_color (C)
|
||||
* d = l – LUM (C)
|
||||
* C += d
|
||||
* return clip_color (C)
|
||||
*
|
||||
* SAT (C) = CH_MAX (C) - CH_MIN (C)
|
||||
*
|
||||
* set_sat (C, s):
|
||||
* if Cmax > Cmin
|
||||
* Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
|
||||
* Cmax = s
|
||||
* else
|
||||
* Cmid = Cmax = 0.0
|
||||
* Cmin = 0.0
|
||||
* return C
|
||||
* if Cmax > Cmin
|
||||
* Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
|
||||
* Cmax = s
|
||||
* else
|
||||
* Cmid = Cmax = 0.0
|
||||
* Cmin = 0.0
|
||||
* return C
|
||||
*/
|
||||
|
||||
/* For premultiplied colors, we need to know what happens when C is
|
||||
* multiplied by a real number. LUM and SAT are linear:
|
||||
*
|
||||
* LUM (r × C) = r × LUM (C) SAT (r × C) = r × SAT (C)
|
||||
* LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C)
|
||||
*
|
||||
* If we extend clip_color with an extra argument a and change
|
||||
*
|
||||
* if x >= 1.0
|
||||
* if x >= 1.0
|
||||
*
|
||||
* into
|
||||
*
|
||||
* if x >= a
|
||||
* if x >= a
|
||||
*
|
||||
* then clip_color is also linear:
|
||||
*
|
||||
* r * clip_color (C, a) = clip_color (r_c, ra);
|
||||
* r * clip_color (C, a) = clip_color (r * C, r * a);
|
||||
*
|
||||
* for positive r.
|
||||
*
|
||||
* Similarly, we can extend set_lum with an extra argument that is just passed
|
||||
* on to clip_color:
|
||||
*
|
||||
* r × set_lum ( C, l, a)
|
||||
* r * set_lum (C, l, a)
|
||||
*
|
||||
* = r × clip_color ( C + l - LUM (C), a)
|
||||
* = r × clip_color (C + l - LUM (C), a)
|
||||
*
|
||||
* = clip_color ( r * C + r × l - LUM (r × C), r * a)
|
||||
* = clip_color (r * C + r × l - r * LUM (C), r * a)
|
||||
*
|
||||
* = set_lum ( r * C, r * l, r * a)
|
||||
* = set_lum (r * C, r * l, r * a)
|
||||
*
|
||||
* Finally, set_sat:
|
||||
*
|
||||
* r * set_sat (C, s) = set_sat (x * C, r * s)
|
||||
* r * set_sat (C, s) = set_sat (x * C, r * s)
|
||||
*
|
||||
* The above holds for all non-zero x because they x'es in the fraction for
|
||||
* The above holds for all non-zero x, because the x'es in the fraction for
|
||||
* C_mid cancel out. Specifically, it holds for x = r:
|
||||
*
|
||||
* r * set_sat (C, s) = set_sat (r_c, rs)
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* So, for the non-separable PDF blend modes, we have (using s, d for
|
||||
* non-premultiplied colors, and S, D for premultiplied:
|
||||
*
|
||||
* Color:
|
||||
*
|
||||
* a_s * a_d * B(s, d)
|
||||
* = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
|
||||
* = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
|
||||
*
|
||||
*
|
||||
* Luminosity:
|
||||
*
|
||||
* a_s * a_d * B(s, d)
|
||||
* = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
|
||||
* = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
|
||||
*
|
||||
*
|
||||
* Saturation:
|
||||
*
|
||||
* a_s * a_d * B(s, d)
|
||||
* = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
|
||||
* = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
|
||||
* a_s * LUM (D), a_s * a_d)
|
||||
* = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
|
||||
*
|
||||
* Hue:
|
||||
*
|
||||
* a_s * a_d * B(s, d)
|
||||
* = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
|
||||
* = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
|
||||
* r * set_sat (C, s) = set_sat (r * C, r * s)
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float r;
|
||||
|
|
@ -658,7 +784,7 @@ clip_color (rgb_t *color, float a)
|
|||
if (n < 0.0f)
|
||||
{
|
||||
t = l - n;
|
||||
if (IS_ZERO (t))
|
||||
if (FLOAT_IS_ZERO (t))
|
||||
{
|
||||
color->r = 0.0f;
|
||||
color->g = 0.0f;
|
||||
|
|
@ -674,7 +800,7 @@ clip_color (rgb_t *color, float a)
|
|||
if (x > a)
|
||||
{
|
||||
t = x - l;
|
||||
if (IS_ZERO (t))
|
||||
if (FLOAT_IS_ZERO (t))
|
||||
{
|
||||
color->r = a;
|
||||
color->g = a;
|
||||
|
|
@ -758,7 +884,7 @@ set_sat (rgb_t *src, float sat)
|
|||
|
||||
t = *max - *min;
|
||||
|
||||
if (IS_ZERO (t))
|
||||
if (FLOAT_IS_ZERO (t))
|
||||
{
|
||||
*mid = *max = 0.0f;
|
||||
}
|
||||
|
|
@ -771,9 +897,12 @@ set_sat (rgb_t *src, float sat)
|
|||
*min = 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hue:
|
||||
* B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
|
||||
/* Hue:
|
||||
*
|
||||
* as * ad * B(s/as, d/as)
|
||||
* = as * ad * set_lum (set_sat (s/as, SAT (d/ad)), LUM (d/ad), 1)
|
||||
* = set_lum (set_sat (ad * s, as * SAT (d)), as * LUM (d), as * ad)
|
||||
*
|
||||
*/
|
||||
static force_inline void
|
||||
blend_hsl_hue (rgb_t *res,
|
||||
|
|
@ -788,9 +917,14 @@ blend_hsl_hue (rgb_t *res,
|
|||
set_lum (res, sa * da, get_lum (dest) * sa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Saturation:
|
||||
* B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
|
||||
/*
|
||||
* Saturation
|
||||
*
|
||||
* as * ad * B(s/as, d/ad)
|
||||
* = as * ad * set_lum (set_sat (d/ad, SAT (s/as)), LUM (d/ad), 1)
|
||||
* = set_lum (as * ad * set_sat (d/ad, SAT (s/as)),
|
||||
* as * LUM (d), as * ad)
|
||||
* = set_lum (set_sat (as * d, ad * SAT (s), as * LUM (d), as * ad))
|
||||
*/
|
||||
static force_inline void
|
||||
blend_hsl_saturation (rgb_t *res,
|
||||
|
|
@ -805,9 +939,12 @@ blend_hsl_saturation (rgb_t *res,
|
|||
set_lum (res, sa * da, get_lum (dest) * sa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Color:
|
||||
* B(Cb, Cs) = set_lum (Cs, LUM (Cb))
|
||||
/*
|
||||
* Color
|
||||
*
|
||||
* as * ad * B(s/as, d/as)
|
||||
* = as * ad * set_lum (s/as, LUM (d/ad), 1)
|
||||
* = set_lum (s * ad, as * LUM (d), as * ad)
|
||||
*/
|
||||
static force_inline void
|
||||
blend_hsl_color (rgb_t *res,
|
||||
|
|
@ -822,8 +959,11 @@ blend_hsl_color (rgb_t *res,
|
|||
}
|
||||
|
||||
/*
|
||||
* Luminosity:
|
||||
* B(Cb, Cs) = set_lum (Cb, LUM (Cs))
|
||||
* Luminosity
|
||||
*
|
||||
* as * ad * B(s/as, d/ad)
|
||||
* = as * ad * set_lum (d/ad, LUM (s/as), 1)
|
||||
* = set_lum (as * d, ad * LUM (s), as * ad)
|
||||
*/
|
||||
static force_inline void
|
||||
blend_hsl_luminosity (rgb_t *res,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,226 +0,0 @@
|
|||
|
||||
#define COMPONENT_SIZE
|
||||
#define MASK
|
||||
#define ONE_HALF
|
||||
|
||||
#define A_SHIFT
|
||||
#define R_SHIFT
|
||||
#define G_SHIFT
|
||||
#define A_MASK
|
||||
#define R_MASK
|
||||
#define G_MASK
|
||||
|
||||
#define RB_MASK
|
||||
#define AG_MASK
|
||||
#define RB_ONE_HALF
|
||||
#define RB_MASK_PLUS_ONE
|
||||
|
||||
#define ALPHA_c(x) ((x) >> A_SHIFT)
|
||||
#define RED_c(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_c(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_c(x) ((x) & MASK)
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define MUL_UNc(a, b, t) \
|
||||
((t) = (a) * (comp2_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UNc(a, b) \
|
||||
(((comp2_t) (a) * MASK + ((b) / 2)) / (b))
|
||||
|
||||
#define ADD_UNc(x, y, t) \
|
||||
((t) = (x) + (y), \
|
||||
(comp4_t) (comp1_t) ((t) | (0 - ((t) >> G_SHIFT))))
|
||||
|
||||
#define DIV_ONE_UNc(x) \
|
||||
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
|
||||
|
||||
/*
|
||||
* The methods below use some tricks to be able to do two color
|
||||
* components at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a) / 255
|
||||
*/
|
||||
#define UNc_rb_MUL_UNc(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) & RB_MASK) * (a); \
|
||||
t += RB_ONE_HALF; \
|
||||
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x &= RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#define UNc_rb_ADD_UNc_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) + (y)); \
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
*/
|
||||
#define UNc_rb_MUL_UNc_rb(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = (x & MASK) * (a & MASK); \
|
||||
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
|
||||
t += RB_ONE_HALF; \
|
||||
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x = t & RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNc(x, a) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
UNc_rb_MUL_UNc (r1__, (a), t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc (r2__, (a), t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255 + y_c
|
||||
*/
|
||||
#define UNcx4_MUL_UNc_ADD_UNcx4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UNc_rb_MUL_UNc (r1__, (a), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UNc_rb_MUL_UNc (r2__, (a), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a + y_c * b) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y); \
|
||||
UNc_rb_MUL_UNc (r1__, (a), t__); \
|
||||
UNc_rb_MUL_UNc (r2__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((y) >> G_SHIFT); \
|
||||
UNc_rb_MUL_UNc (r2__, (a), t__); \
|
||||
UNc_rb_MUL_UNc (r3__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNcx4(x, a) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255 + y_c
|
||||
*/
|
||||
#define UNcx4_MUL_UNcx4_ADD_UNcx4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((a) >> G_SHIFT); \
|
||||
UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c + y_c * b) / 255
|
||||
*/
|
||||
#define UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UNc_rb_MUL_UNc_rb (r1__, r2__, t__); \
|
||||
r2__ = (y); \
|
||||
UNc_rb_MUL_UNc (r2__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc_rb (r2__, r3__, t__); \
|
||||
r3__ = (y) >> G_SHIFT; \
|
||||
UNc_rb_MUL_UNc (r3__, (b), t__); \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#define UNcx4_ADD_UNcx4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
comp4_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x) & RB_MASK; \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UNc_rb_ADD_UNc_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include "pixman-combine32.h"
|
||||
|
||||
static force_inline uint32_t
|
||||
combine_mask (const uint32_t src, const uint32_t mask)
|
||||
{
|
||||
uint32_t s, m;
|
||||
|
||||
m = mask >> A_SHIFT;
|
||||
|
||||
if (!m)
|
||||
return 0;
|
||||
s = src;
|
||||
|
||||
UN8x4_MUL_UN8 (s, m);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
combine_src_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mask)
|
||||
memcpy (dest, src, width * sizeof (uint16_t));
|
||||
else
|
||||
{
|
||||
uint16_t *d = (uint16_t*)dest;
|
||||
uint16_t *src16 = (uint16_t*)src;
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
if ((*mask & 0xff000000) == 0xff000000) {
|
||||
// it's likely worth special casing
|
||||
// fully opaque because it avoids
|
||||
// the cost of conversion as well the multiplication
|
||||
*(d + i) = *src16;
|
||||
} else {
|
||||
// the mask is still 32bits
|
||||
uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
|
||||
*(d + i) = convert_8888_to_0565(s);
|
||||
}
|
||||
mask++;
|
||||
src16++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
combine_over_u (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * dest,
|
||||
const uint32_t * src,
|
||||
const uint32_t * mask,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mask)
|
||||
memcpy (dest, src, width * sizeof (uint16_t));
|
||||
else
|
||||
{
|
||||
uint16_t *d = (uint16_t*)dest;
|
||||
uint16_t *src16 = (uint16_t*)src;
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
if ((*mask & 0xff000000) == 0xff000000) {
|
||||
// it's likely worth special casing
|
||||
// fully opaque because it avoids
|
||||
// the cost of conversion as well the multiplication
|
||||
*(d + i) = *src16;
|
||||
} else if ((*mask & 0xff000000) == 0x00000000) {
|
||||
// keep the dest the same
|
||||
} else {
|
||||
// the mask is still 32bits
|
||||
uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
|
||||
uint32_t ia = ALPHA_8 (~s);
|
||||
uint32_t d32 = convert_0565_to_8888(*(d + i));
|
||||
UN8x4_MUL_UN8_ADD_UN8x4 (d32, ia, s);
|
||||
*(d + i) = convert_8888_to_0565(d32);
|
||||
}
|
||||
mask++;
|
||||
src16++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_pixman_setup_combiner_functions_16 (pixman_implementation_t *imp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < PIXMAN_N_OPERATORS; i++) {
|
||||
imp->combine_16[i] = NULL;
|
||||
}
|
||||
imp->combine_16[PIXMAN_OP_SRC] = combine_src_u;
|
||||
imp->combine_16[PIXMAN_OP_OVER] = combine_over_u;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -12,7 +12,7 @@
|
|||
#define RB_MASK 0xff00ff
|
||||
#define AG_MASK 0xff00ff00
|
||||
#define RB_ONE_HALF 0x800080
|
||||
#define RB_MASK_PLUS_ONE 0x10000100
|
||||
#define RB_MASK_PLUS_ONE 0x1000100
|
||||
|
||||
#define ALPHA_8(x) ((x) >> A_SHIFT)
|
||||
#define RED_8(x) (((x) >> R_SHIFT) & MASK)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,230 +0,0 @@
|
|||
/* WARNING: This file is generated by combine.pl from combine.inc.
|
||||
Please edit one of those files rather than this one. */
|
||||
|
||||
#line 1 "pixman-combine.c.template"
|
||||
|
||||
#define COMPONENT_SIZE 16
|
||||
#define MASK 0xffffULL
|
||||
#define ONE_HALF 0x8000ULL
|
||||
|
||||
#define A_SHIFT 16 * 3
|
||||
#define R_SHIFT 16 * 2
|
||||
#define G_SHIFT 16
|
||||
#define A_MASK 0xffff000000000000ULL
|
||||
#define R_MASK 0xffff00000000ULL
|
||||
#define G_MASK 0xffff0000ULL
|
||||
|
||||
#define RB_MASK 0xffff0000ffffULL
|
||||
#define AG_MASK 0xffff0000ffff0000ULL
|
||||
#define RB_ONE_HALF 0x800000008000ULL
|
||||
#define RB_MASK_PLUS_ONE 0x10000000010000ULL
|
||||
|
||||
#define ALPHA_16(x) ((x) >> A_SHIFT)
|
||||
#define RED_16(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_16(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_16(x) ((x) & MASK)
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define MUL_UN16(a, b, t) \
|
||||
((t) = (a) * (uint32_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UN16(a, b) \
|
||||
(((uint32_t) (a) * MASK + ((b) / 2)) / (b))
|
||||
|
||||
#define ADD_UN16(x, y, t) \
|
||||
((t) = (x) + (y), \
|
||||
(uint64_t) (uint16_t) ((t) | (0 - ((t) >> G_SHIFT))))
|
||||
|
||||
#define DIV_ONE_UN16(x) \
|
||||
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
|
||||
|
||||
/*
|
||||
* The methods below use some tricks to be able to do two color
|
||||
* components at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a) / 255
|
||||
*/
|
||||
#define UN16_rb_MUL_UN16(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) & RB_MASK) * (a); \
|
||||
t += RB_ONE_HALF; \
|
||||
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x &= RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#define UN16_rb_ADD_UN16_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) + (y)); \
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
*/
|
||||
#define UN16_rb_MUL_UN16_rb(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = (x & MASK) * (a & MASK); \
|
||||
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
|
||||
t += RB_ONE_HALF; \
|
||||
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x = t & RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
UN16_rb_MUL_UN16 (r1__, (a), t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16 (r2__, (a), t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255 + y_c
|
||||
*/
|
||||
#define UN16x4_MUL_UN16_ADD_UN16x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN16_rb_MUL_UN16 (r1__, (a), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN16_rb_MUL_UN16 (r2__, (a), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a + y_c * b) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y); \
|
||||
UN16_rb_MUL_UN16 (r1__, (a), t__); \
|
||||
UN16_rb_MUL_UN16 (r2__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((y) >> G_SHIFT); \
|
||||
UN16_rb_MUL_UN16 (r2__, (a), t__); \
|
||||
UN16_rb_MUL_UN16 (r3__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16x4(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255 + y_c
|
||||
*/
|
||||
#define UN16x4_MUL_UN16x4_ADD_UN16x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((a) >> G_SHIFT); \
|
||||
UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c + y_c * b) / 255
|
||||
*/
|
||||
#define UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
|
||||
r2__ = (y); \
|
||||
UN16_rb_MUL_UN16 (r2__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
|
||||
r3__ = (y) >> G_SHIFT; \
|
||||
UN16_rb_MUL_UN16 (r3__, (b), t__); \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#define UN16x4_ADD_UN16x4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
uint64_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x) & RB_MASK; \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
|
@ -18,6 +18,12 @@
|
|||
# define FUNC ((const char*) ("???"))
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define unlikely(expr) __builtin_expect ((expr), 0)
|
||||
#else
|
||||
# define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
|
|
@ -106,6 +112,8 @@
|
|||
/* Sun Studio 8 visibility */
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
# define PIXMAN_EXPORT __global
|
||||
#elif defined (_MSC_VER) || defined(__MINGW32__)
|
||||
# define PIXMAN_EXPORT PIXMAN_API
|
||||
#else
|
||||
# define PIXMAN_EXPORT
|
||||
#endif
|
||||
|
|
@ -131,12 +139,10 @@
|
|||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(__MINGW32__) || defined(PIXMAN_USE_XP_DLL_TLS_WORKAROUND)
|
||||
#elif defined(__MINGW32__)
|
||||
|
||||
# define _NO_W32_PSEUDO_MODIFIERS
|
||||
# include <windows.h>
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static volatile int tls_ ## name ## _initialized = 0; \
|
||||
|
|
@ -193,7 +199,7 @@
|
|||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(HAVE_PTHREAD_SETSPECIFIC)
|
||||
#elif defined(HAVE_PTHREADS)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,10 @@ coordinates_to_parameter (double x, double y, double angle)
|
|||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
conical_get_scanline (pixman_iter_t *iter,
|
||||
const uint32_t *mask,
|
||||
int Bpp,
|
||||
pixman_gradient_walker_write_t write_pixel)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
|
|
@ -61,7 +64,7 @@ conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
|||
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
conical_gradient_t *conical = (conical_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
uint32_t *end = buffer + width * (Bpp / 4);
|
||||
pixman_gradient_walker_t walker;
|
||||
pixman_bool_t affine = TRUE;
|
||||
double cx = 1.;
|
||||
|
|
@ -109,11 +112,12 @@ conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
|||
{
|
||||
double t = coordinates_to_parameter (rx, ry, conical->angle);
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (
|
||||
&walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
|
||||
write_pixel (&walker,
|
||||
(pixman_fixed_48_16_t)pixman_double_to_fixed (t),
|
||||
buffer);
|
||||
}
|
||||
|
||||
++buffer;
|
||||
buffer += (Bpp / 4);
|
||||
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
|
|
@ -144,11 +148,12 @@ conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
|||
|
||||
t = coordinates_to_parameter (x, y, conical->angle);
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (
|
||||
&walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
|
||||
write_pixel (&walker,
|
||||
(pixman_fixed_48_16_t)pixman_double_to_fixed (t),
|
||||
buffer);
|
||||
}
|
||||
|
||||
++buffer;
|
||||
buffer += (Bpp / 4);
|
||||
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
|
|
@ -160,15 +165,18 @@ conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
|||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
return conical_get_scanline (iter, mask, 4,
|
||||
_pixman_gradient_walker_write_narrow);
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = conical_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
return conical_get_scanline (iter, NULL, 16,
|
||||
_pixman_gradient_walker_write_wide);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1,765 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2021 Moonchild Productions
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the names of the authors not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The authors make no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(USE_ARM_SIMD) && defined(_MSC_VER)
|
||||
/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#ifdef USE_VMX
|
||||
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-maltivec -mabi=altivec", as gcc would try to save vector register
|
||||
* across function calls causing SIGILL on cpus without Altivec/vmx.
|
||||
*/
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static volatile pixman_bool_t have_vmx = TRUE;
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
size_t length = sizeof(have_vmx);
|
||||
int error =
|
||||
sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0);
|
||||
|
||||
if (error)
|
||||
have_vmx = FALSE;
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#elif defined (__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC };
|
||||
size_t length = sizeof(have_vmx);
|
||||
int error =
|
||||
sysctl (mib, 2, &have_vmx, &length, NULL, 0);
|
||||
|
||||
if (error != 0)
|
||||
have_vmx = FALSE;
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#elif defined (__linux__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/auxvec.h>
|
||||
#include <asm/cputable.h>
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
char fname[64];
|
||||
unsigned long buf[64];
|
||||
ssize_t count = 0;
|
||||
pid_t pid;
|
||||
int fd, i;
|
||||
|
||||
pid = getpid ();
|
||||
snprintf (fname, sizeof(fname) - 1, "/proc/%d/auxv", pid);
|
||||
|
||||
fd = open (fname, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
for (i = 0; i <= (count / sizeof(unsigned long)); i += 2)
|
||||
{
|
||||
/* Read more if buf is empty... */
|
||||
if (i == (count / sizeof(unsigned long)))
|
||||
{
|
||||
count = read (fd, buf, sizeof(buf));
|
||||
if (count <= 0)
|
||||
break;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (buf[i] == AT_HWCAP)
|
||||
{
|
||||
have_vmx = !!(buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC);
|
||||
initialized = TRUE;
|
||||
break;
|
||||
}
|
||||
else if (buf[i] == AT_NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
if (!initialized)
|
||||
{
|
||||
/* Something went wrong. Assume 'no' rather than playing
|
||||
fragile tricks with catching SIGILL. */
|
||||
have_vmx = FALSE;
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
static jmp_buf jump_env;
|
||||
|
||||
static void
|
||||
vmx_test (int sig,
|
||||
siginfo_t *si,
|
||||
void * unused)
|
||||
{
|
||||
longjmp (jump_env, 1);
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
pixman_have_vmx (void)
|
||||
{
|
||||
struct sigaction sa, osa;
|
||||
int jmp_result;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_sigaction = vmx_test;
|
||||
sigaction (SIGILL, &sa, &osa);
|
||||
jmp_result = setjmp (jump_env);
|
||||
if (jmp_result == 0)
|
||||
{
|
||||
asm volatile ( "vor 0, 0, 0" );
|
||||
}
|
||||
sigaction (SIGILL, &osa, NULL);
|
||||
have_vmx = (jmp_result == 0);
|
||||
initialized = TRUE;
|
||||
}
|
||||
return have_vmx;
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* USE_VMX */
|
||||
|
||||
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if defined(USE_ARM_SIMD)
|
||||
extern int pixman_msvc_try_arm_simd_op ();
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t have_arm_simd = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
__try {
|
||||
pixman_msvc_try_arm_simd_op ();
|
||||
have_arm_simd = TRUE;
|
||||
} __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) {
|
||||
have_arm_simd = FALSE;
|
||||
}
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return have_arm_simd;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_SIMD */
|
||||
|
||||
#if defined(USE_ARM_NEON)
|
||||
extern int pixman_msvc_try_arm_neon_op ();
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_neon (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t have_arm_neon = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
__try
|
||||
{
|
||||
pixman_msvc_try_arm_neon_op ();
|
||||
have_arm_neon = TRUE;
|
||||
}
|
||||
__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
|
||||
{
|
||||
have_arm_neon = FALSE;
|
||||
}
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return have_arm_neon;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_NEON */
|
||||
|
||||
#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */
|
||||
|
||||
/* Detection of ARM NEON on iOS is fairly simple because iOS binaries
|
||||
* contain separate executable images for each processor architecture.
|
||||
* So all we have to do is detect the armv7 architecture build. The
|
||||
* operating system automatically runs the armv7 binary for armv7 devices
|
||||
* and the armv6 binary for armv6 devices.
|
||||
*/
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
#if defined(USE_ARM_SIMD)
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_neon (void)
|
||||
{
|
||||
#if defined(USE_ARM_NEON) && defined(__ARM_NEON__)
|
||||
/* This is an armv7 cpu build */
|
||||
return TRUE;
|
||||
#else
|
||||
/* This is an armv6 cpu build */
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_arm_iwmmxt (void)
|
||||
{
|
||||
#if defined(USE_ARM_IWMMXT)
|
||||
return FALSE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined (__linux__) /* linux ELF */
|
||||
|
||||
static pixman_bool_t arm_has_v7 = FALSE;
|
||||
static pixman_bool_t arm_has_v6 = FALSE;
|
||||
static pixman_bool_t arm_has_vfp = FALSE;
|
||||
static pixman_bool_t arm_has_neon = FALSE;
|
||||
static pixman_bool_t arm_has_iwmmxt = FALSE;
|
||||
static pixman_bool_t arm_tests_initialized = FALSE;
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <elf.h>
|
||||
|
||||
static void
|
||||
pixman_arm_read_auxv_or_cpu_features ()
|
||||
{
|
||||
int fd;
|
||||
Elf32_auxv_t aux;
|
||||
|
||||
fd = open ("/proc/self/auxv", O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
|
||||
{
|
||||
if (aux.a_type == AT_HWCAP)
|
||||
{
|
||||
uint32_t hwcap = aux.a_un.a_val;
|
||||
/* hardcode these values to avoid depending on specific
|
||||
* versions of the hwcap header, e.g. HWCAP_NEON
|
||||
*/
|
||||
arm_has_vfp = (hwcap & 64) != 0;
|
||||
arm_has_iwmmxt = (hwcap & 512) != 0;
|
||||
/* this flag is only present on kernel 2.6.29 */
|
||||
arm_has_neon = (hwcap & 4096) != 0;
|
||||
}
|
||||
else if (aux.a_type == AT_PLATFORM)
|
||||
{
|
||||
const char *plat = (const char*) aux.a_un.a_val;
|
||||
if (strncmp (plat, "v7l", 3) == 0)
|
||||
{
|
||||
arm_has_v7 = TRUE;
|
||||
arm_has_v6 = TRUE;
|
||||
}
|
||||
else if (strncmp (plat, "v6l", 3) == 0)
|
||||
{
|
||||
arm_has_v6 = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
||||
arm_tests_initialized = TRUE;
|
||||
}
|
||||
|
||||
#if defined(USE_ARM_SIMD)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_simd (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv_or_cpu_features ();
|
||||
|
||||
return arm_has_v6;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_SIMD */
|
||||
|
||||
#if defined(USE_ARM_NEON)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_neon (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv_or_cpu_features ();
|
||||
|
||||
return arm_has_neon;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_NEON */
|
||||
|
||||
#if defined(USE_ARM_IWMMXT)
|
||||
pixman_bool_t
|
||||
pixman_have_arm_iwmmxt (void)
|
||||
{
|
||||
if (!arm_tests_initialized)
|
||||
pixman_arm_read_auxv_or_cpu_features ();
|
||||
|
||||
return arm_has_iwmmxt;
|
||||
}
|
||||
|
||||
#endif /* USE_ARM_IWMMXT */
|
||||
|
||||
#else /* !_MSC_VER && !Linux elf */
|
||||
|
||||
#define pixman_have_arm_simd() FALSE
|
||||
#define pixman_have_arm_neon() FALSE
|
||||
#define pixman_have_arm_iwmmxt() FALSE
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
|
||||
|
||||
#if defined(USE_MIPS_DSPR2)
|
||||
|
||||
#if defined (__linux__) /* linux ELF */
|
||||
|
||||
pixman_bool_t
|
||||
pixman_have_mips_dspr2 (void)
|
||||
{
|
||||
const char *search_string = "MIPS 74K";
|
||||
const char *file_name = "/proc/cpuinfo";
|
||||
/* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux.
|
||||
* It is based on /proc/cpuinfo, which reveals hardware configuration
|
||||
* to user-space applications. According to MIPS (early 2010), no similar
|
||||
* facility is universally available on the MIPS architectures, so it's up
|
||||
* to individual OSes to provide such.
|
||||
*
|
||||
* Only currently available MIPS core that supports DSPr2 is 74K.
|
||||
*/
|
||||
|
||||
char cpuinfo_line[256];
|
||||
|
||||
FILE *f = NULL;
|
||||
|
||||
if ((f = fopen (file_name, "r")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
|
||||
{
|
||||
if (strstr (cpuinfo_line, search_string) != NULL)
|
||||
{
|
||||
fclose (f);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
|
||||
/* Did not find string in the proc file. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else /* linux ELF */
|
||||
|
||||
#define pixman_have_mips_dspr2() FALSE
|
||||
|
||||
#endif /* linux ELF */
|
||||
|
||||
#endif /* USE_MIPS_DSPR2 */
|
||||
|
||||
#if defined(USE_X86_MMX) || defined(USE_SSE2)
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise
|
||||
* that would lead to SIGILL instructions on old CPUs that don't have
|
||||
* it.
|
||||
*/
|
||||
#if !defined(__amd64__) && !defined(__x86_64__) && !defined(_M_AMD64)
|
||||
|
||||
#ifdef HAVE_GETISAX
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_FEATURES = 0,
|
||||
MMX = 0x1,
|
||||
MMX_EXTENSIONS = 0x2,
|
||||
SSE = 0x6,
|
||||
SSE2 = 0x8,
|
||||
CMOV = 0x10
|
||||
} cpu_features_t;
|
||||
|
||||
|
||||
static unsigned int
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
unsigned int features = 0;
|
||||
unsigned int result = 0;
|
||||
|
||||
#ifdef HAVE_GETISAX
|
||||
if (getisax (&result, 1))
|
||||
{
|
||||
if (result & AV_386_CMOV)
|
||||
features |= CMOV;
|
||||
if (result & AV_386_MMX)
|
||||
features |= MMX;
|
||||
if (result & AV_386_AMD_MMX)
|
||||
features |= MMX_EXTENSIONS;
|
||||
if (result & AV_386_SSE)
|
||||
features |= SSE;
|
||||
if (result & AV_386_SSE2)
|
||||
features |= SSE2;
|
||||
}
|
||||
#else
|
||||
char vendor[13];
|
||||
#ifdef _MSC_VER
|
||||
int vendor0 = 0, vendor1, vendor2;
|
||||
#endif
|
||||
vendor[0] = 0;
|
||||
vendor[12] = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* see p. 118 of amd64 instruction set manual Vol3 */
|
||||
/* We need to be careful about the handling of %ebx and
|
||||
* %esp here. We can't declare either one as clobbered
|
||||
* since they are special registers (%ebx is the "PIC
|
||||
* register" holding an offset to global data, %esp the
|
||||
* stack pointer), so we need to make sure they have their
|
||||
* original values when we access the output operands.
|
||||
*/
|
||||
__asm__ (
|
||||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"mov %%eax, %%ecx\n"
|
||||
"xor $0x00200000, %%eax\n"
|
||||
"push %%eax\n"
|
||||
"popf\n"
|
||||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"mov $0x0, %%edx\n"
|
||||
"xor %%ecx, %%eax\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"mov $0x00000000, %%eax\n"
|
||||
"push %%ebx\n"
|
||||
"cpuid\n"
|
||||
"mov %%ebx, %%eax\n"
|
||||
"pop %%ebx\n"
|
||||
"mov %%eax, %1\n"
|
||||
"mov %%edx, %2\n"
|
||||
"mov %%ecx, %3\n"
|
||||
"mov $0x00000001, %%eax\n"
|
||||
"push %%ebx\n"
|
||||
"cpuid\n"
|
||||
"pop %%ebx\n"
|
||||
"1:\n"
|
||||
"mov %%edx, %0\n"
|
||||
: "=r" (result),
|
||||
"=m" (vendor[0]),
|
||||
"=m" (vendor[4]),
|
||||
"=m" (vendor[8])
|
||||
:
|
||||
: "%eax", "%ecx", "%edx"
|
||||
);
|
||||
|
||||
#elif defined (_MSC_VER)
|
||||
|
||||
_asm {
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 00200000h
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
mov edx, 0
|
||||
xor eax, ecx
|
||||
jz nocpuid
|
||||
|
||||
mov eax, 0
|
||||
push ebx
|
||||
cpuid
|
||||
mov eax, ebx
|
||||
pop ebx
|
||||
mov vendor0, eax
|
||||
mov vendor1, edx
|
||||
mov vendor2, ecx
|
||||
mov eax, 1
|
||||
push ebx
|
||||
cpuid
|
||||
pop ebx
|
||||
nocpuid:
|
||||
mov result, edx
|
||||
}
|
||||
memmove (vendor + 0, &vendor0, 4);
|
||||
memmove (vendor + 4, &vendor1, 4);
|
||||
memmove (vendor + 8, &vendor2, 4);
|
||||
|
||||
#else
|
||||
# error unsupported compiler
|
||||
#endif
|
||||
|
||||
features = 0;
|
||||
if (result)
|
||||
{
|
||||
/* result now contains the standard feature bits */
|
||||
if (result & (1 << 15))
|
||||
features |= CMOV;
|
||||
if (result & (1 << 23))
|
||||
features |= MMX;
|
||||
if (result & (1 << 25))
|
||||
features |= SSE;
|
||||
if (result & (1 << 26))
|
||||
features |= SSE2;
|
||||
if ((features & MMX) && !(features & SSE) &&
|
||||
(strcmp (vendor, "AuthenticAMD") == 0 ||
|
||||
strcmp (vendor, "Geode by NSC") == 0))
|
||||
{
|
||||
/* check for AMD MMX extensions */
|
||||
#ifdef __GNUC__
|
||||
__asm__ (
|
||||
" push %%ebx\n"
|
||||
" mov $0x80000000, %%eax\n"
|
||||
" cpuid\n"
|
||||
" xor %%edx, %%edx\n"
|
||||
" cmp $0x1, %%eax\n"
|
||||
" jge 2f\n"
|
||||
" mov $0x80000001, %%eax\n"
|
||||
" cpuid\n"
|
||||
"2:\n"
|
||||
" pop %%ebx\n"
|
||||
" mov %%edx, %0\n"
|
||||
: "=r" (result)
|
||||
:
|
||||
: "%eax", "%ecx", "%edx"
|
||||
);
|
||||
#elif defined _MSC_VER
|
||||
_asm {
|
||||
push ebx
|
||||
mov eax, 80000000h
|
||||
cpuid
|
||||
xor edx, edx
|
||||
cmp eax, 1
|
||||
jge notamd
|
||||
mov eax, 80000001h
|
||||
cpuid
|
||||
notamd:
|
||||
pop ebx
|
||||
mov result, edx
|
||||
}
|
||||
#endif
|
||||
if (result & (1 << 22))
|
||||
features |= MMX_EXTENSIONS;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_GETISAX */
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#ifdef USE_X86_MMX
|
||||
static pixman_bool_t
|
||||
pixman_have_mmx (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t mmx_present;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
unsigned int features = detect_cpu_features ();
|
||||
mmx_present = (features & (MMX | MMX_EXTENSIONS)) == (MMX | MMX_EXTENSIONS);
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return mmx_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
static pixman_bool_t
|
||||
pixman_have_sse2 (void)
|
||||
{
|
||||
static pixman_bool_t initialized = FALSE;
|
||||
static pixman_bool_t sse2_present;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
unsigned int features = detect_cpu_features ();
|
||||
sse2_present = (features & (MMX | MMX_EXTENSIONS | SSE | SSE2)) == (MMX | MMX_EXTENSIONS | SSE | SSE2);
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return sse2_present;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else /* __amd64__ */
|
||||
#ifdef USE_X86_MMX
|
||||
#define pixman_have_mmx() TRUE
|
||||
#endif
|
||||
#ifdef USE_SSE2
|
||||
#define pixman_have_sse2() TRUE
|
||||
#endif
|
||||
#endif /* __amd64__ */
|
||||
#endif
|
||||
|
||||
static pixman_bool_t
|
||||
disabled (const char *name)
|
||||
{
|
||||
const char *env;
|
||||
|
||||
if ((env = getenv ("PIXMAN_DISABLE")))
|
||||
{
|
||||
do
|
||||
{
|
||||
const char *end;
|
||||
int len;
|
||||
|
||||
if ((end = strchr (env, ' ')))
|
||||
len = end - env;
|
||||
else
|
||||
len = strlen (env);
|
||||
|
||||
if (strlen (name) == len && strncmp (name, env, len) == 0)
|
||||
{
|
||||
printf ("pixman: Disabled %s implementation\n", name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
env += len;
|
||||
}
|
||||
while (*env++);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_choose_implementation (void)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
imp = _pixman_implementation_create_general();
|
||||
|
||||
if (!disabled ("fast"))
|
||||
imp = _pixman_implementation_create_fast_path (imp);
|
||||
|
||||
#ifdef USE_X86_MMX
|
||||
if (!disabled ("mmx") && pixman_have_mmx ())
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (!disabled ("sse2") && pixman_have_sse2 ())
|
||||
imp = _pixman_implementation_create_sse2 (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_SIMD
|
||||
if (!disabled ("arm-simd") && pixman_have_arm_simd ())
|
||||
imp = _pixman_implementation_create_arm_simd (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_IWMMXT
|
||||
if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ())
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARM_NEON
|
||||
if (!disabled ("arm-neon") && pixman_have_arm_neon ())
|
||||
imp = _pixman_implementation_create_arm_neon (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MIPS_DSPR2
|
||||
if (!disabled ("mips-dspr2") && pixman_have_mips_dspr2 ())
|
||||
imp = _pixman_implementation_create_mips_dspr2 (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VMX
|
||||
if (!disabled ("vmx") && pixman_have_vmx ())
|
||||
imp = _pixman_implementation_create_vmx (imp);
|
||||
#endif
|
||||
|
||||
imp = _pixman_implementation_create_noop (imp);
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
#define R16_BITS 5
|
||||
#define G16_BITS 6
|
||||
#define B16_BITS 5
|
||||
|
||||
#define R16_SHIFT (B16_BITS + G16_BITS)
|
||||
#define G16_SHIFT (B16_BITS)
|
||||
#define B16_SHIFT 0
|
||||
|
||||
#define MASK 0xff
|
||||
#define ONE_HALF 0x80
|
||||
|
||||
#define A_SHIFT 8 * 3
|
||||
#define R_SHIFT 8 * 2
|
||||
#define G_SHIFT 8
|
||||
#define A_MASK 0xff000000
|
||||
#define R_MASK 0xff0000
|
||||
#define G_MASK 0xff00
|
||||
|
||||
#define RB_MASK 0xff00ff
|
||||
#define AG_MASK 0xff00ff00
|
||||
#define RB_ONE_HALF 0x800080
|
||||
#define RB_MASK_PLUS_ONE 0x10000100
|
||||
|
||||
#define ALPHA_8(x) ((x) >> A_SHIFT)
|
||||
#define RED_8(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_8(x) ((x) & MASK)
|
||||
|
||||
// This uses the same dithering technique that Skia does.
|
||||
// It is essentially preturbing the lower bit based on the
|
||||
// high bit
|
||||
static inline uint16_t dither_32_to_16(uint32_t c)
|
||||
{
|
||||
uint8_t b = BLUE_8(c);
|
||||
uint8_t g = GREEN_8(c);
|
||||
uint8_t r = RED_8(c);
|
||||
r = ((r << 1) - ((r >> (8 - R16_BITS) << (8 - R16_BITS)) | (r >> R16_BITS))) >> (8 - R16_BITS);
|
||||
g = ((g << 1) - ((g >> (8 - G16_BITS) << (8 - G16_BITS)) | (g >> G16_BITS))) >> (8 - G16_BITS);
|
||||
b = ((b << 1) - ((b >> (8 - B16_BITS) << (8 - B16_BITS)) | (b >> B16_BITS))) >> (8 - B16_BITS);
|
||||
return ((r << R16_SHIFT) | (g << G16_SHIFT) | (b << B16_SHIFT));
|
||||
}
|
||||
|
||||
static inline uint16_t dither_8888_to_0565(uint32_t color, pixman_bool_t toggle)
|
||||
{
|
||||
// alternate between a preturbed truncation and a regular truncation
|
||||
if (toggle) {
|
||||
return dither_32_to_16(color);
|
||||
} else {
|
||||
return convert_8888_to_0565(color);
|
||||
}
|
||||
}
|
||||
|
|
@ -55,9 +55,8 @@ RASTERIZE_EDGES (pixman_image_t *image,
|
|||
*
|
||||
* (The AA case does a similar adjustment in RENDER_SAMPLES_X)
|
||||
*/
|
||||
/* we cast to unsigned to get defined behaviour for overflow */
|
||||
lx = (unsigned)lx + X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
rx = (unsigned)rx + X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
lx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
rx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
#endif
|
||||
/* clip X */
|
||||
if (lx < 0)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -109,14 +109,16 @@ general_cubic (double x, double B, double C)
|
|||
|
||||
if (ax < 1)
|
||||
{
|
||||
return ((12 - 9 * B - 6 * C) * ax * ax * ax +
|
||||
(-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
|
||||
return (((12 - 9 * B - 6 * C) * ax +
|
||||
(-18 + 12 * B + 6 * C)) * ax * ax +
|
||||
(6 - 2 * B)) / 6;
|
||||
}
|
||||
else if (ax >= 1 && ax < 2)
|
||||
else if (ax < 2)
|
||||
{
|
||||
return ((-B - 6 * C) * ax * ax * ax +
|
||||
(6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
|
||||
ax + (8 * B + 24 * C)) / 6;
|
||||
return ((((-B - 6 * C) * ax +
|
||||
(6 * B + 30 * C)) * ax +
|
||||
(-12 * B - 48 * C)) * ax +
|
||||
(8 * B + 24 * C)) / 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -141,7 +143,7 @@ static const filter_info_t filters[] =
|
|||
{ PIXMAN_KERNEL_BOX, box_kernel, 1.0 },
|
||||
{ PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 },
|
||||
{ PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
|
||||
{ PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 6 * SIGMA },
|
||||
{ PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 5.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 },
|
||||
|
|
@ -160,18 +162,21 @@ integral (pixman_kernel_t kernel1, double x1,
|
|||
pixman_kernel_t kernel2, double scale, double x2,
|
||||
double width)
|
||||
{
|
||||
/* If the integration interval crosses zero, break it into
|
||||
* two separate integrals. This ensures that filters such
|
||||
* as LINEAR that are not differentiable at 0 will still
|
||||
* integrate properly.
|
||||
if (kernel1 == PIXMAN_KERNEL_BOX && kernel2 == PIXMAN_KERNEL_BOX)
|
||||
{
|
||||
return width;
|
||||
}
|
||||
/* The LINEAR filter is not differentiable at 0, so if the
|
||||
* integration interval crosses zero, break it into two
|
||||
* separate integrals.
|
||||
*/
|
||||
if (x1 < 0 && x1 + width > 0)
|
||||
else if (kernel1 == PIXMAN_KERNEL_LINEAR && x1 < 0 && x1 + width > 0)
|
||||
{
|
||||
return
|
||||
integral (kernel1, x1, kernel2, scale, x2, - x1) +
|
||||
integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
|
||||
}
|
||||
else if (x2 < 0 && x2 + width > 0)
|
||||
else if (kernel2 == PIXMAN_KERNEL_LINEAR && x2 < 0 && x2 + width > 0)
|
||||
{
|
||||
return
|
||||
integral (kernel1, x1, kernel2, scale, x2, - x2) +
|
||||
|
|
@ -189,13 +194,19 @@ integral (pixman_kernel_t kernel1, double x1,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Integration via Simpson's rule */
|
||||
#define N_SEGMENTS 128
|
||||
/* Integration via Simpson's rule
|
||||
* See http://www.intmath.com/integration/6-simpsons-rule.php
|
||||
* 12 segments (6 cubic approximations) seems to produce best
|
||||
* result for lanczos3.linear, which was the combination that
|
||||
* showed the most errors. This makes sense as the lanczos3
|
||||
* filter is 6 wide.
|
||||
*/
|
||||
#define N_SEGMENTS 12
|
||||
#define SAMPLE(a1, a2) \
|
||||
(filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
|
||||
|
||||
double s = 0.0;
|
||||
double h = width / (double)N_SEGMENTS;
|
||||
double h = width / N_SEGMENTS;
|
||||
int i;
|
||||
|
||||
s = SAMPLE (x1, x2);
|
||||
|
|
@ -204,11 +215,14 @@ integral (pixman_kernel_t kernel1, double x1,
|
|||
{
|
||||
double a1 = x1 + h * i;
|
||||
double a2 = x2 + h * i;
|
||||
s += 4 * SAMPLE (a1, a2);
|
||||
}
|
||||
|
||||
for (i = 2; i < N_SEGMENTS; i += 2)
|
||||
{
|
||||
double a1 = x1 + h * i;
|
||||
double a2 = x2 + h * i;
|
||||
s += 2 * SAMPLE (a1, a2);
|
||||
|
||||
if (i >= 2 && i < N_SEGMENTS - 1)
|
||||
s += 4 * SAMPLE (a1, a2);
|
||||
}
|
||||
|
||||
s += SAMPLE (x1 + width, x2 + width);
|
||||
|
|
@ -217,25 +231,17 @@ integral (pixman_kernel_t kernel1, double x1,
|
|||
}
|
||||
}
|
||||
|
||||
static pixman_fixed_t *
|
||||
create_1d_filter (int *width,
|
||||
static void
|
||||
create_1d_filter (int width,
|
||||
pixman_kernel_t reconstruct,
|
||||
pixman_kernel_t sample,
|
||||
double scale,
|
||||
int n_phases)
|
||||
int n_phases,
|
||||
pixman_fixed_t *p)
|
||||
{
|
||||
pixman_fixed_t *params, *p;
|
||||
double step;
|
||||
double size;
|
||||
int i;
|
||||
|
||||
size = scale * filters[sample].width + filters[reconstruct].width;
|
||||
*width = ceil (size);
|
||||
|
||||
p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
|
||||
if (!params)
|
||||
return NULL;
|
||||
|
||||
step = 1.0 / n_phases;
|
||||
|
||||
for (i = 0; i < n_phases; ++i)
|
||||
|
|
@ -243,15 +249,15 @@ create_1d_filter (int *width,
|
|||
double frac = step / 2.0 + i * step;
|
||||
pixman_fixed_t new_total;
|
||||
int x, x1, x2;
|
||||
double total;
|
||||
double total, e;
|
||||
|
||||
/* Sample convolution of reconstruction and sampling
|
||||
* filter. See rounding.txt regarding the rounding
|
||||
* and sample positions.
|
||||
*/
|
||||
|
||||
x1 = ceil (frac - *width / 2.0 - 0.5);
|
||||
x2 = x1 + *width;
|
||||
x1 = ceil (frac - width / 2.0 - 0.5);
|
||||
x2 = x1 + width;
|
||||
|
||||
total = 0;
|
||||
for (x = x1; x < x2; ++x)
|
||||
|
|
@ -274,29 +280,154 @@ create_1d_filter (int *width,
|
|||
ihigh - ilow);
|
||||
}
|
||||
|
||||
total += c;
|
||||
*p++ = (pixman_fixed_t)(c * 65535.0 + 0.5);
|
||||
*p = (pixman_fixed_t)floor (c * 65536.0 + 0.5);
|
||||
total += *p;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Normalize */
|
||||
p -= *width;
|
||||
total = 1 / total;
|
||||
/* Normalize, with error diffusion */
|
||||
p -= width;
|
||||
total = 65536.0 / total;
|
||||
new_total = 0;
|
||||
e = 0.0;
|
||||
for (x = x1; x < x2; ++x)
|
||||
{
|
||||
pixman_fixed_t t = (*p) * total + 0.5;
|
||||
double v = (*p) * total + e;
|
||||
pixman_fixed_t t = floor (v + 0.5);
|
||||
|
||||
e = v - t;
|
||||
new_total += t;
|
||||
*p++ = t;
|
||||
}
|
||||
|
||||
if (new_total != pixman_fixed_1)
|
||||
*(p - *width / 2) += (pixman_fixed_1 - new_total);
|
||||
/* pixman_fixed_e's worth of error may remain; put it
|
||||
* at the first sample, since that is the only one that
|
||||
* hasn't had any error diffused into it.
|
||||
*/
|
||||
*(p - width) += pixman_fixed_1 - new_total;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
filter_width (pixman_kernel_t reconstruct, pixman_kernel_t sample, double size)
|
||||
{
|
||||
return ceil (filters[reconstruct].width + size * filters[sample].width);
|
||||
}
|
||||
|
||||
#ifdef PIXMAN_GNUPLOT
|
||||
|
||||
/* If enable-gnuplot is configured, then you can pipe the output of a
|
||||
* pixman-using program to gnuplot and get a continuously-updated plot
|
||||
* of the horizontal filter. This works well with demos/scale to test
|
||||
* the filter generation.
|
||||
*
|
||||
* The plot is all the different subposition filters shuffled
|
||||
* together. This is misleading in a few cases:
|
||||
*
|
||||
* IMPULSE.BOX - goes up and down as the subfilters have different
|
||||
* numbers of non-zero samples
|
||||
* IMPULSE.TRIANGLE - somewhat crooked for the same reason
|
||||
* 1-wide filters - looks triangular, but a 1-wide box would be more
|
||||
* accurate
|
||||
*/
|
||||
static void
|
||||
gnuplot_filter (int width, int n_phases, const pixman_fixed_t* p)
|
||||
{
|
||||
double step;
|
||||
int i, j;
|
||||
int first;
|
||||
|
||||
step = 1.0 / n_phases;
|
||||
|
||||
printf ("set style line 1 lc rgb '#0060ad' lt 1 lw 0.5 pt 7 pi 1 ps 0.5\n");
|
||||
printf ("plot [x=%g:%g] '-' with linespoints ls 1\n", -width*0.5, width*0.5);
|
||||
/* Print a point at the origin so that y==0 line is included: */
|
||||
printf ("0 0\n\n");
|
||||
|
||||
/* The position of the first sample of the phase corresponding to
|
||||
* frac is given by:
|
||||
*
|
||||
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
|
||||
*
|
||||
* We have to find the frac that minimizes this expression.
|
||||
*
|
||||
* For odd widths, we have
|
||||
*
|
||||
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
|
||||
* = ceil (frac) + K - frac
|
||||
* = 1 + K - frac
|
||||
*
|
||||
* for some K, so this is minimized when frac is maximized and
|
||||
* strictly growing with frac. So for odd widths, we can simply
|
||||
* start at the last phase and go backwards.
|
||||
*
|
||||
* For even widths, we have
|
||||
*
|
||||
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
|
||||
* = ceil (frac - 0.5) + K - frac
|
||||
*
|
||||
* The graph for this function (ignoring K) looks like this:
|
||||
*
|
||||
* 0.5
|
||||
* | |\
|
||||
* | | \
|
||||
* | | \
|
||||
* 0 | | \
|
||||
* |\ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* -0.5 | \|
|
||||
* ---------------------------------
|
||||
* 0 0.5 1
|
||||
*
|
||||
* So in this case we need to start with the phase whose frac is
|
||||
* less than, but as close as possible to 0.5, then go backwards
|
||||
* until we hit the first phase, then wrap around to the last
|
||||
* phase and continue backwards.
|
||||
*
|
||||
* Which phase is as close as possible 0.5? The locations of the
|
||||
* sampling point corresponding to the kth phase is given by
|
||||
* 1/(2 * n_phases) + k / n_phases:
|
||||
*
|
||||
* 1/(2 * n_phases) + k / n_phases = 0.5
|
||||
*
|
||||
* from which it follows that
|
||||
*
|
||||
* k = (n_phases - 1) / 2
|
||||
*
|
||||
* rounded down is the phase in question.
|
||||
*/
|
||||
if (width & 1)
|
||||
first = n_phases - 1;
|
||||
else
|
||||
first = (n_phases - 1) / 2;
|
||||
|
||||
for (j = 0; j < width; ++j)
|
||||
{
|
||||
for (i = 0; i < n_phases; ++i)
|
||||
{
|
||||
int phase = first - i;
|
||||
double frac, pos;
|
||||
|
||||
if (phase < 0)
|
||||
phase = n_phases + phase;
|
||||
|
||||
frac = step / 2.0 + phase * step;
|
||||
pos = ceil (frac - width / 2.0 - 0.5) + 0.5 - frac + j;
|
||||
|
||||
printf ("%g %g\n",
|
||||
pos,
|
||||
pixman_fixed_to_double (*(p + phase * width + j)));
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
printf ("e\n");
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
|
||||
* with the given kernels and scale parameters
|
||||
*/
|
||||
|
|
@ -313,38 +444,35 @@ pixman_filter_create_separable_convolution (int *n_values,
|
|||
{
|
||||
double sx = fabs (pixman_fixed_to_double (scale_x));
|
||||
double sy = fabs (pixman_fixed_to_double (scale_y));
|
||||
pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
|
||||
pixman_fixed_t *params;
|
||||
int subsample_x, subsample_y;
|
||||
int width, height;
|
||||
|
||||
width = filter_width (reconstruct_x, sample_x, sx);
|
||||
subsample_x = (1 << subsample_bits_x);
|
||||
|
||||
height = filter_width (reconstruct_y, sample_y, sy);
|
||||
subsample_y = (1 << subsample_bits_y);
|
||||
|
||||
horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x);
|
||||
vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y);
|
||||
|
||||
if (!horz || !vert)
|
||||
goto out;
|
||||
|
||||
*n_values = 4 + width * subsample_x + height * subsample_y;
|
||||
|
||||
params = malloc (*n_values * sizeof (pixman_fixed_t));
|
||||
if (!params)
|
||||
goto out;
|
||||
return NULL;
|
||||
|
||||
params[0] = pixman_int_to_fixed (width);
|
||||
params[1] = pixman_int_to_fixed (height);
|
||||
params[2] = pixman_int_to_fixed (subsample_bits_x);
|
||||
params[3] = pixman_int_to_fixed (subsample_bits_y);
|
||||
|
||||
memcpy (params + 4, horz,
|
||||
width * subsample_x * sizeof (pixman_fixed_t));
|
||||
memcpy (params + 4 + width * subsample_x, vert,
|
||||
height * subsample_y * sizeof (pixman_fixed_t));
|
||||
create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x,
|
||||
params + 4);
|
||||
create_1d_filter (height, reconstruct_y, sample_y, sy, subsample_y,
|
||||
params + 4 + width * subsample_x);
|
||||
|
||||
out:
|
||||
free (horz);
|
||||
free (vert);
|
||||
#ifdef PIXMAN_GNUPLOT
|
||||
gnuplot_filter(width, subsample_x, params + 4);
|
||||
#endif
|
||||
|
||||
return params;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,43 +37,47 @@
|
|||
#include <string.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static pixman_bool_t
|
||||
general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
static void
|
||||
general_iter_init (pixman_iter_t *iter, const pixman_iter_info_t *info)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
if (image->type == LINEAR)
|
||||
_pixman_linear_gradient_iter_init (image, iter);
|
||||
else if (image->type == RADIAL)
|
||||
switch (image->type)
|
||||
{
|
||||
case BITS:
|
||||
if ((iter->iter_flags & ITER_SRC) == ITER_SRC)
|
||||
_pixman_bits_image_src_iter_init (image, iter);
|
||||
else
|
||||
_pixman_bits_image_dest_iter_init (image, iter);
|
||||
break;
|
||||
|
||||
case LINEAR:
|
||||
_pixman_linear_gradient_iter_init (image, iter);
|
||||
break;
|
||||
|
||||
case RADIAL:
|
||||
_pixman_radial_gradient_iter_init (image, iter);
|
||||
else if (image->type == CONICAL)
|
||||
break;
|
||||
|
||||
case CONICAL:
|
||||
_pixman_conical_gradient_iter_init (image, iter);
|
||||
else if (image->type == BITS)
|
||||
_pixman_bits_image_src_iter_init (image, iter);
|
||||
else if (image->type == SOLID)
|
||||
break;
|
||||
|
||||
case SOLID:
|
||||
_pixman_log_error (FUNC, "Solid image not handled by noop");
|
||||
else
|
||||
break;
|
||||
|
||||
default:
|
||||
_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
|
||||
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
static const pixman_iter_info_t general_iters[] =
|
||||
{
|
||||
if (iter->image->type == BITS)
|
||||
{
|
||||
_pixman_bits_image_dest_iter_init (iter->image, iter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pixman_log_error (FUNC, "Trying to write to a non-writable image");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
{ PIXMAN_any, 0, 0, general_iter_init, NULL, NULL },
|
||||
{ PIXMAN_null },
|
||||
};
|
||||
|
||||
typedef struct op_info_t op_info_t;
|
||||
struct op_info_t
|
||||
|
|
@ -105,62 +109,75 @@ static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
|
|||
|
||||
#define SCANLINE_BUFFER_LENGTH 8192
|
||||
|
||||
static pixman_bool_t
|
||||
operator_needs_division (pixman_op_t op)
|
||||
{
|
||||
static const uint8_t needs_division[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* SATURATE */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* DISJOINT */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* CONJOINT */
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, /* blend ops */
|
||||
};
|
||||
|
||||
return needs_division[op];
|
||||
}
|
||||
|
||||
static void
|
||||
general_composite_rect (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
PIXMAN_COMPOSITE_ARGS (info);
|
||||
uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
|
||||
uint8_t stack_scanline_buffer[3 * SCANLINE_BUFFER_LENGTH];
|
||||
uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
|
||||
uint8_t *src_buffer, *mask_buffer, *dest_buffer;
|
||||
pixman_iter_t src_iter, mask_iter, dest_iter;
|
||||
pixman_combine_32_func_t compose;
|
||||
pixman_bool_t component_alpha;
|
||||
iter_flags_t narrow, src_iter_flags;
|
||||
iter_flags_t rgb16;
|
||||
iter_flags_t width_flag, src_iter_flags;
|
||||
int Bpp;
|
||||
int i;
|
||||
|
||||
if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
|
||||
if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(dest_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
!(operator_needs_division (op)) &&
|
||||
(dest_image->bits.dither == PIXMAN_DITHER_NONE))
|
||||
{
|
||||
narrow = ITER_NARROW;
|
||||
width_flag = ITER_NARROW;
|
||||
Bpp = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
narrow = 0;
|
||||
width_flag = ITER_WIDE;
|
||||
Bpp = 16;
|
||||
}
|
||||
|
||||
// XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps
|
||||
// by having it deal more specifically with different intermediate formats
|
||||
if (
|
||||
(dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) &&
|
||||
( op == PIXMAN_OP_SRC ||
|
||||
(op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE))
|
||||
)
|
||||
) {
|
||||
rgb16 = ITER_16;
|
||||
} else {
|
||||
rgb16 = 0;
|
||||
}
|
||||
#define ALIGN(addr) \
|
||||
((uint8_t *)((((uintptr_t)(addr)) + 15) & (~15)))
|
||||
|
||||
if (width <= 0 || _pixman_multiply_overflows_int (width, Bpp * 3))
|
||||
return;
|
||||
|
||||
if (width * Bpp > SCANLINE_BUFFER_LENGTH)
|
||||
if (width * Bpp * 3 > sizeof (stack_scanline_buffer) - 15 * 3)
|
||||
{
|
||||
scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
|
||||
scanline_buffer = pixman_malloc_ab_plus_c (width, Bpp * 3, 15 * 3);
|
||||
|
||||
if (!scanline_buffer)
|
||||
return;
|
||||
|
||||
memset (scanline_buffer, 0, width * Bpp * 3 + 15 * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (stack_scanline_buffer, 0, sizeof (stack_scanline_buffer));
|
||||
}
|
||||
|
||||
src_buffer = scanline_buffer;
|
||||
mask_buffer = src_buffer + width * Bpp;
|
||||
dest_buffer = mask_buffer + width * Bpp;
|
||||
src_buffer = ALIGN (scanline_buffer);
|
||||
mask_buffer = ALIGN (src_buffer + width * Bpp);
|
||||
dest_buffer = ALIGN (mask_buffer + width * Bpp);
|
||||
|
||||
if (!narrow)
|
||||
if (width_flag == ITER_WIDE)
|
||||
{
|
||||
/* To make sure there aren't any NANs in the buffers */
|
||||
memset (src_buffer, 0, width * Bpp);
|
||||
|
|
@ -169,11 +186,12 @@ general_composite_rect (pixman_implementation_t *imp,
|
|||
}
|
||||
|
||||
/* src iter */
|
||||
src_iter_flags = narrow | op_flags[op].src | rgb16;
|
||||
src_iter_flags = width_flag | op_flags[op].src | ITER_SRC;
|
||||
|
||||
_pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
|
||||
src_x, src_y, width, height,
|
||||
src_buffer, src_iter_flags, info->src_flags);
|
||||
_pixman_implementation_iter_init (imp->toplevel, &src_iter, src_image,
|
||||
src_x, src_y, width, height,
|
||||
src_buffer, src_iter_flags,
|
||||
info->src_flags);
|
||||
|
||||
/* mask iter */
|
||||
if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
|
|
@ -185,23 +203,21 @@ general_composite_rect (pixman_implementation_t *imp,
|
|||
mask_image = NULL;
|
||||
}
|
||||
|
||||
component_alpha =
|
||||
mask_image &&
|
||||
mask_image->common.type == BITS &&
|
||||
mask_image->common.component_alpha &&
|
||||
PIXMAN_FORMAT_RGB (mask_image->bits.format);
|
||||
component_alpha = mask_image && mask_image->common.component_alpha;
|
||||
|
||||
_pixman_implementation_src_iter_init (
|
||||
imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height,
|
||||
mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags);
|
||||
_pixman_implementation_iter_init (
|
||||
imp->toplevel, &mask_iter,
|
||||
mask_image, mask_x, mask_y, width, height, mask_buffer,
|
||||
ITER_SRC | width_flag | (component_alpha? 0 : ITER_IGNORE_RGB),
|
||||
info->mask_flags);
|
||||
|
||||
/* dest iter */
|
||||
_pixman_implementation_dest_iter_init (
|
||||
_pixman_implementation_iter_init (
|
||||
imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
|
||||
dest_buffer, narrow | op_flags[op].dst | rgb16, info->dest_flags);
|
||||
dest_buffer, ITER_DEST | width_flag | op_flags[op].dst, info->dest_flags);
|
||||
|
||||
compose = _pixman_implementation_lookup_combiner (
|
||||
imp->toplevel, op, component_alpha, narrow, !!rgb16);
|
||||
imp->toplevel, op, component_alpha, width_flag != ITER_WIDE);
|
||||
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
|
|
@ -216,6 +232,13 @@ general_composite_rect (pixman_implementation_t *imp,
|
|||
dest_iter.write_back (&dest_iter);
|
||||
}
|
||||
|
||||
if (src_iter.fini)
|
||||
src_iter.fini (&src_iter);
|
||||
if (mask_iter.fini)
|
||||
mask_iter.fini (&mask_iter);
|
||||
if (dest_iter.fini)
|
||||
dest_iter.fini (&dest_iter);
|
||||
|
||||
if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
|
||||
free (scanline_buffer);
|
||||
}
|
||||
|
|
@ -231,12 +254,10 @@ _pixman_implementation_create_general (void)
|
|||
{
|
||||
pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
|
||||
|
||||
_pixman_setup_combiner_functions_16 (imp);
|
||||
_pixman_setup_combiner_functions_32 (imp);
|
||||
_pixman_setup_combiner_functions_float (imp);
|
||||
|
||||
imp->src_iter_init = general_src_iter_init;
|
||||
imp->dest_iter_init = general_dest_iter_init;
|
||||
imp->iter_info = general_iters;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -391,6 +391,9 @@ box32_intersect (pixman_box32_t *dest,
|
|||
return dest->x2 > dest->x1 && dest->y2 > dest->y1;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
|
||||
__attribute__((__force_align_arg_pointer__))
|
||||
#endif
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_glyphs_no_mask (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
|
|
@ -630,6 +633,9 @@ out:
|
|||
* - Trim the mask to the destination clip/image?
|
||||
* - Trim composite region based on sources, when the op ignores 0s.
|
||||
*/
|
||||
#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
|
||||
__attribute__((__force_align_arg_pointer__))
|
||||
#endif
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_glyphs (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
|
|
|
|||
|
|
@ -37,11 +37,14 @@ _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
|
|||
walker->stops = gradient->stops;
|
||||
walker->left_x = 0;
|
||||
walker->right_x = 0x10000;
|
||||
walker->stepper = 0;
|
||||
walker->left_ag = 0;
|
||||
walker->left_rb = 0;
|
||||
walker->right_ag = 0;
|
||||
walker->right_rb = 0;
|
||||
walker->a_s = 0.0f;
|
||||
walker->a_b = 0.0f;
|
||||
walker->r_s = 0.0f;
|
||||
walker->r_b = 0.0f;
|
||||
walker->g_s = 0.0f;
|
||||
walker->g_b = 0.0f;
|
||||
walker->b_s = 0.0f;
|
||||
walker->b_b = 0.0f;
|
||||
walker->repeat = repeat;
|
||||
|
||||
walker->need_reset = TRUE;
|
||||
|
|
@ -51,10 +54,13 @@ static void
|
|||
gradient_walker_reset (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t pos)
|
||||
{
|
||||
int32_t x, left_x, right_x;
|
||||
int64_t x, left_x, right_x;
|
||||
pixman_color_t *left_c, *right_c;
|
||||
int n, count = walker->num_stops;
|
||||
pixman_gradient_stop_t *stops = walker->stops;
|
||||
float la, lr, lg, lb;
|
||||
float ra, rr, rg, rb;
|
||||
float lx, rx;
|
||||
|
||||
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
|
|
@ -116,57 +122,143 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
|
|||
left_c = right_c;
|
||||
}
|
||||
|
||||
walker->left_x = left_x;
|
||||
walker->right_x = right_x;
|
||||
walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8);
|
||||
walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8);
|
||||
walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8);
|
||||
walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
|
||||
/* The alpha/red/green/blue channels are scaled to be in [0, 1].
|
||||
* This ensures that after premultiplication all channels will
|
||||
* be in the [0, 1] interval.
|
||||
*/
|
||||
la = (left_c->alpha * (1.0f/257.0f));
|
||||
lr = (left_c->red * (1.0f/257.0f));
|
||||
lg = (left_c->green * (1.0f/257.0f));
|
||||
lb = (left_c->blue * (1.0f/257.0f));
|
||||
|
||||
if (walker->left_x == walker->right_x ||
|
||||
(walker->left_ag == walker->right_ag &&
|
||||
walker->left_rb == walker->right_rb))
|
||||
ra = (right_c->alpha * (1.0f/257.0f));
|
||||
rr = (right_c->red * (1.0f/257.0f));
|
||||
rg = (right_c->green * (1.0f/257.0f));
|
||||
rb = (right_c->blue * (1.0f/257.0f));
|
||||
|
||||
lx = left_x * (1.0f/65536.0f);
|
||||
rx = right_x * (1.0f/65536.0f);
|
||||
|
||||
if (FLOAT_IS_ZERO (rx - lx) || left_x == INT32_MIN || right_x == INT32_MAX)
|
||||
{
|
||||
walker->stepper = 0;
|
||||
walker->a_s = walker->r_s = walker->g_s = walker->b_s = 0.0f;
|
||||
walker->a_b = (la + ra) / 510.0f;
|
||||
walker->r_b = (lr + rr) / 510.0f;
|
||||
walker->g_b = (lg + rg) / 510.0f;
|
||||
walker->b_b = (lb + rb) / 510.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t width = right_x - left_x;
|
||||
walker->stepper = ((1 << 24) + width / 2) / width;
|
||||
float w_rec = 1.0f / (rx - lx);
|
||||
|
||||
walker->a_b = (la * rx - ra * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->r_b = (lr * rx - rr * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->g_b = (lg * rx - rg * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->b_b = (lb * rx - rb * lx) * w_rec * (1.0f/255.0f);
|
||||
|
||||
walker->a_s = (ra - la) * w_rec * (1.0f/255.0f);
|
||||
walker->r_s = (rr - lr) * w_rec * (1.0f/255.0f);
|
||||
walker->g_s = (rg - lg) * w_rec * (1.0f/255.0f);
|
||||
walker->b_s = (rb - lb) * w_rec * (1.0f/255.0f);
|
||||
}
|
||||
|
||||
walker->left_x = left_x;
|
||||
walker->right_x = right_x;
|
||||
|
||||
walker->need_reset = FALSE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x)
|
||||
static argb_t
|
||||
pixman_gradient_walker_pixel_float (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x)
|
||||
{
|
||||
int dist, idist;
|
||||
uint32_t t1, t2, a, color;
|
||||
argb_t f;
|
||||
float y;
|
||||
|
||||
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
|
||||
gradient_walker_reset (walker, x);
|
||||
|
||||
dist = ((int)(x - walker->left_x) * walker->stepper) >> 16;
|
||||
idist = 256 - dist;
|
||||
y = x * (1.0f / 65536.0f);
|
||||
|
||||
/* combined INTERPOLATE and premultiply */
|
||||
t1 = walker->left_rb * idist + walker->right_rb * dist;
|
||||
t1 = (t1 >> 8) & 0xff00ff;
|
||||
f.a = walker->a_s * y + walker->a_b;
|
||||
f.r = f.a * (walker->r_s * y + walker->r_b);
|
||||
f.g = f.a * (walker->g_s * y + walker->g_b);
|
||||
f.b = f.a * (walker->b_s * y + walker->b_b);
|
||||
|
||||
t2 = walker->left_ag * idist + walker->right_ag * dist;
|
||||
t2 &= 0xff00ff00;
|
||||
|
||||
color = t2 & 0xff000000;
|
||||
a = t2 >> 24;
|
||||
|
||||
t1 = t1 * a + 0x800080;
|
||||
t1 = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
|
||||
|
||||
t2 = (t2 >> 8) * a + 0x800080;
|
||||
t2 = (t2 + ((t2 >> 8) & 0xff00ff));
|
||||
|
||||
return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
|
||||
return f;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
pixman_gradient_walker_pixel_32 (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x)
|
||||
{
|
||||
argb_t f;
|
||||
float y;
|
||||
|
||||
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
|
||||
gradient_walker_reset (walker, x);
|
||||
|
||||
y = x * (1.0f / 65536.0f);
|
||||
|
||||
/* Instead of [0...1] for ARGB, we want [0...255],
|
||||
* multiply alpha with 255 and the color channels
|
||||
* also get multiplied by the alpha multiplier.
|
||||
*
|
||||
* We don't use pixman_contract_from_float because it causes a 2x
|
||||
* slowdown to do so, and the values are already normalized,
|
||||
* so we don't have to worry about values < 0.f or > 1.f
|
||||
*/
|
||||
f.a = 255.f * (walker->a_s * y + walker->a_b);
|
||||
f.r = f.a * (walker->r_s * y + walker->r_b);
|
||||
f.g = f.a * (walker->g_s * y + walker->g_b);
|
||||
f.b = f.a * (walker->b_s * y + walker->b_b);
|
||||
|
||||
return (((uint32_t)(f.a + .5f) << 24) & 0xff000000) |
|
||||
(((uint32_t)(f.r + .5f) << 16) & 0x00ff0000) |
|
||||
(((uint32_t)(f.g + .5f) << 8) & 0x0000ff00) |
|
||||
(((uint32_t)(f.b + .5f) >> 0) & 0x000000ff);
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_write_narrow (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x,
|
||||
uint32_t *buffer)
|
||||
{
|
||||
*buffer = pixman_gradient_walker_pixel_32 (walker, x);
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_write_wide (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x,
|
||||
uint32_t *buffer)
|
||||
{
|
||||
*(argb_t *)buffer = pixman_gradient_walker_pixel_float (walker, x);
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_fill_narrow (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x,
|
||||
uint32_t *buffer,
|
||||
uint32_t *end)
|
||||
{
|
||||
register uint32_t color;
|
||||
|
||||
color = pixman_gradient_walker_pixel_32 (walker, x);
|
||||
while (buffer < end)
|
||||
*buffer++ = color;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_fill_wide (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x,
|
||||
uint32_t *buffer,
|
||||
uint32_t *end)
|
||||
{
|
||||
register argb_t color;
|
||||
argb_t *buffer_wide = (argb_t *)buffer;
|
||||
argb_t *end_wide = (argb_t *)end;
|
||||
|
||||
color = pixman_gradient_walker_pixel_float (walker, x);
|
||||
while (buffer_wide < end_wide)
|
||||
*buffer_wide++ = color;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,25 +33,6 @@
|
|||
|
||||
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
|
||||
|
||||
/**
|
||||
** bug 1293598 - clean up every pointer after free to avoid
|
||||
** "dereferencing freed memory" problem
|
||||
**/
|
||||
#define PIXMAN_POSION
|
||||
|
||||
static void
|
||||
free_memory (void** p)
|
||||
{
|
||||
#ifdef PIXMAN_POISON
|
||||
if (*p) {
|
||||
#endif
|
||||
free (*p);
|
||||
#ifdef PIXMAN_POISON
|
||||
*p = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_property_changed (pixman_image_t *image)
|
||||
{
|
||||
|
|
@ -164,8 +145,8 @@ _pixman_image_fini (pixman_image_t *image)
|
|||
|
||||
pixman_region32_fini (&common->clip_region);
|
||||
|
||||
free_memory (&common->transform);
|
||||
free_memory (&common->filter_params);
|
||||
free (common->transform);
|
||||
free (common->filter_params);
|
||||
|
||||
if (common->alpha_map)
|
||||
pixman_image_unref ((pixman_image_t *)common->alpha_map);
|
||||
|
|
@ -177,8 +158,7 @@ _pixman_image_fini (pixman_image_t *image)
|
|||
if (image->gradient.stops)
|
||||
{
|
||||
/* See _pixman_init_gradient() for an explanation of the - 1 */
|
||||
void *addr = image->gradient.stops - 1;
|
||||
free_memory (&addr);
|
||||
free (image->gradient.stops - 1);
|
||||
}
|
||||
|
||||
/* This will trigger if someone adds a property_changed
|
||||
|
|
@ -189,11 +169,8 @@ _pixman_image_fini (pixman_image_t *image)
|
|||
image->common.property_changed == gradient_property_changed);
|
||||
}
|
||||
|
||||
if (image->type == BITS && image->bits.free_me) {
|
||||
free_memory (&image->bits.free_me);
|
||||
image->bits.bits = NULL;
|
||||
}
|
||||
|
||||
if (image->type == BITS && image->bits.free_me)
|
||||
free (image->bits.free_me);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -233,7 +210,7 @@ pixman_image_unref (pixman_image_t *image)
|
|||
{
|
||||
if (_pixman_image_fini (image))
|
||||
{
|
||||
free_memory (&image);
|
||||
free (image);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -358,37 +335,47 @@ compute_image_info (pixman_image_t *image)
|
|||
{
|
||||
flags |= FAST_PATH_NEAREST_FILTER;
|
||||
}
|
||||
else if (
|
||||
/* affine and integer translation components in matrix ... */
|
||||
((flags & FAST_PATH_AFFINE_TRANSFORM) &&
|
||||
!pixman_fixed_frac (image->common.transform->matrix[0][2] |
|
||||
image->common.transform->matrix[1][2])) &&
|
||||
(
|
||||
/* ... combined with a simple rotation */
|
||||
(flags & (FAST_PATH_ROTATE_90_TRANSFORM |
|
||||
FAST_PATH_ROTATE_180_TRANSFORM |
|
||||
FAST_PATH_ROTATE_270_TRANSFORM)) ||
|
||||
/* ... or combined with a simple non-rotated translation */
|
||||
(image->common.transform->matrix[0][0] == pixman_fixed_1 &&
|
||||
image->common.transform->matrix[1][1] == pixman_fixed_1 &&
|
||||
image->common.transform->matrix[0][1] == 0 &&
|
||||
image->common.transform->matrix[1][0] == 0)
|
||||
)
|
||||
)
|
||||
else if (flags & FAST_PATH_AFFINE_TRANSFORM)
|
||||
{
|
||||
/* FIXME: there are some affine-test failures, showing that
|
||||
* handling of BILINEAR and NEAREST filter is not quite
|
||||
* equivalent when getting close to 32K for the translation
|
||||
* components of the matrix. That's likely some bug, but for
|
||||
* now just skip BILINEAR->NEAREST optimization in this case.
|
||||
/* Suppose the transform is
|
||||
*
|
||||
* [ t00, t01, t02 ]
|
||||
* [ t10, t11, t12 ]
|
||||
* [ 0, 0, 1 ]
|
||||
*
|
||||
* and the destination coordinates are (n + 0.5, m + 0.5). Then
|
||||
* the transformed x coordinate is:
|
||||
*
|
||||
* tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02
|
||||
* = t00 * n + t01 * m + t02 + (t00 + t01) * 0.5
|
||||
*
|
||||
* which implies that if t00, t01 and t02 are all integers
|
||||
* and (t00 + t01) is odd, then tx will be an integer plus 0.5,
|
||||
* which means a BILINEAR filter will reduce to NEAREST. The same
|
||||
* applies in the y direction
|
||||
*/
|
||||
pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
|
||||
if (image->common.transform->matrix[0][2] <= magic_limit &&
|
||||
image->common.transform->matrix[1][2] <= magic_limit &&
|
||||
image->common.transform->matrix[0][2] >= -magic_limit &&
|
||||
image->common.transform->matrix[1][2] >= -magic_limit)
|
||||
pixman_fixed_t (*t)[3] = image->common.transform->matrix;
|
||||
|
||||
if ((pixman_fixed_frac (
|
||||
t[0][0] | t[0][1] | t[0][2] |
|
||||
t[1][0] | t[1][1] | t[1][2]) == 0) &&
|
||||
(pixman_fixed_to_int (
|
||||
(t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1)
|
||||
{
|
||||
flags |= FAST_PATH_NEAREST_FILTER;
|
||||
/* FIXME: there are some affine-test failures, showing that
|
||||
* handling of BILINEAR and NEAREST filter is not quite
|
||||
* equivalent when getting close to 32K for the translation
|
||||
* components of the matrix. That's likely some bug, but for
|
||||
* now just skip BILINEAR->NEAREST optimization in this case.
|
||||
*/
|
||||
pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
|
||||
if (image->common.transform->matrix[0][2] <= magic_limit &&
|
||||
image->common.transform->matrix[1][2] <= magic_limit &&
|
||||
image->common.transform->matrix[0][2] >= -magic_limit &&
|
||||
image->common.transform->matrix[1][2] >= -magic_limit)
|
||||
{
|
||||
flags |= FAST_PATH_NEAREST_FILTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -483,10 +470,6 @@ compute_image_info (pixman_image_t *image)
|
|||
|
||||
if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
|
||||
flags &= ~FAST_PATH_NARROW_FORMAT;
|
||||
|
||||
if (image->bits.format == PIXMAN_r5g6b5)
|
||||
flags |= FAST_PATH_16_FORMAT;
|
||||
|
||||
break;
|
||||
|
||||
case RADIAL:
|
||||
|
|
@ -529,8 +512,10 @@ compute_image_info (pixman_image_t *image)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Alpha map */
|
||||
if (!image->common.alpha_map)
|
||||
/* Alpha maps are only supported for BITS images, so it's always
|
||||
* safe to ignore their presense for non-BITS images
|
||||
*/
|
||||
if (!image->common.alpha_map || image->type != BITS)
|
||||
{
|
||||
flags |= FAST_PATH_NO_ALPHA_MAP;
|
||||
}
|
||||
|
|
@ -699,6 +684,41 @@ pixman_image_set_repeat (pixman_image_t *image,
|
|||
image_property_changed (image);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_dither (pixman_image_t *image,
|
||||
pixman_dither_t dither)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
{
|
||||
if (image->bits.dither == dither)
|
||||
return;
|
||||
|
||||
image->bits.dither = dither;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_image_set_dither_offset (pixman_image_t *image,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
if (image->type == BITS)
|
||||
{
|
||||
if (image->bits.dither_offset_x == offset_x &&
|
||||
image->bits.dither_offset_y == offset_y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
image->bits.dither_offset_x = offset_x;
|
||||
image->bits.dither_offset_y = offset_y;
|
||||
|
||||
image_property_changed (image);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_bool_t
|
||||
pixman_image_set_filter (pixman_image_t * image,
|
||||
pixman_filter_t filter,
|
||||
|
|
@ -857,6 +877,10 @@ pixman_image_set_accessors (pixman_image_t * image,
|
|||
|
||||
if (image->type == BITS)
|
||||
{
|
||||
/* Accessors only work for <= 32 bpp. */
|
||||
if (PIXMAN_FORMAT_BPP(image->bits.format) > 32)
|
||||
return_if_fail (!read_func && !write_func);
|
||||
|
||||
image->bits.read_func = read_func;
|
||||
image->bits.write_func = write_func;
|
||||
|
||||
|
|
@ -936,7 +960,7 @@ _pixman_image_get_solid (pixman_implementation_t *imp,
|
|||
else if (image->bits.format == PIXMAN_x8r8g8b8)
|
||||
result = image->bits.bits[0] | 0xff000000;
|
||||
else if (image->bits.format == PIXMAN_a8)
|
||||
result = (*(uint8_t *)image->bits.bits) << 24;
|
||||
result = (uint32_t)(*(uint8_t *)image->bits.bits) << 24;
|
||||
else
|
||||
goto otherwise;
|
||||
}
|
||||
|
|
@ -945,12 +969,15 @@ _pixman_image_get_solid (pixman_implementation_t *imp,
|
|||
pixman_iter_t iter;
|
||||
|
||||
otherwise:
|
||||
_pixman_implementation_src_iter_init (
|
||||
_pixman_implementation_iter_init (
|
||||
imp, &iter, image, 0, 0, 1, 1,
|
||||
(uint8_t *)&result,
|
||||
ITER_NARROW, image->common.flags);
|
||||
ITER_NARROW | ITER_SRC, image->common.flags);
|
||||
|
||||
result = *iter.get_scanline (&iter, NULL);
|
||||
|
||||
if (iter.fini)
|
||||
iter.fini (&iter);
|
||||
}
|
||||
|
||||
/* If necessary, convert RGB <--> BGR. */
|
||||
|
|
|
|||
|
|
@ -90,15 +90,7 @@ _pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
|
|||
/* Check cache for fast paths */
|
||||
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
|
||||
|
||||
/* Bug 1324130 - For compatibility with Windows XP, we have to use Tls
|
||||
* functions for the per-thread fast-path cache instead of the safer
|
||||
* __declspec(thread) mechanism. If the Tls functions fail to set up
|
||||
* the storage for some reason, cache will end up null here. As a
|
||||
* temporary workaround, just check that cache is not null before
|
||||
* using it. The implementation lookup will still function without the
|
||||
* fast-path cache, however, it will incur a slow linear search.
|
||||
*/
|
||||
if (cache) for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
|
||||
for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
|
||||
{
|
||||
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
|
||||
|
||||
|
|
@ -158,12 +150,19 @@ _pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
|
|||
}
|
||||
|
||||
/* We should never reach this point */
|
||||
_pixman_log_error (FUNC, "No known composite function\n");
|
||||
_pixman_log_error (
|
||||
FUNC,
|
||||
"No composite function found\n"
|
||||
"\n"
|
||||
"The most likely cause of this is that this system has issues with\n"
|
||||
"thread local storage\n");
|
||||
|
||||
*out_imp = NULL;
|
||||
*out_func = dummy_composite_rect;
|
||||
return;
|
||||
|
||||
update_cache:
|
||||
if (cache && i)
|
||||
if (i)
|
||||
{
|
||||
while (i--)
|
||||
cache->cache[i + 1] = cache->cache[i];
|
||||
|
|
@ -194,8 +193,7 @@ pixman_combine_32_func_t
|
|||
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
pixman_bool_t component_alpha,
|
||||
pixman_bool_t narrow,
|
||||
pixman_bool_t rgb16)
|
||||
pixman_bool_t narrow)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
|
|
@ -219,8 +217,6 @@ _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
|
|||
f = imp->combine_32_ca[op];
|
||||
break;
|
||||
}
|
||||
if (rgb16)
|
||||
f = (pixman_combine_32_func_t *)imp->combine_16[op];
|
||||
|
||||
if (f)
|
||||
return f;
|
||||
|
|
@ -289,50 +285,26 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
static uint32_t *
|
||||
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
iter->image = image;
|
||||
iter->buffer = (uint32_t *)buffer;
|
||||
iter->x = x;
|
||||
iter->y = y;
|
||||
iter->width = width;
|
||||
iter->height = height;
|
||||
iter->iter_flags = iter_flags;
|
||||
iter->image_flags = image_flags;
|
||||
|
||||
while (imp)
|
||||
{
|
||||
if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
|
||||
return TRUE;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
void
|
||||
_pixman_implementation_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
{
|
||||
pixman_format_code_t format;
|
||||
|
||||
iter->image = image;
|
||||
iter->buffer = (uint32_t *)buffer;
|
||||
iter->x = x;
|
||||
|
|
@ -341,16 +313,40 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
|
|||
iter->height = height;
|
||||
iter->iter_flags = iter_flags;
|
||||
iter->image_flags = image_flags;
|
||||
iter->fini = NULL;
|
||||
|
||||
if (!iter->image)
|
||||
{
|
||||
iter->get_scanline = get_scanline_null;
|
||||
return;
|
||||
}
|
||||
|
||||
format = iter->image->common.extended_format_code;
|
||||
|
||||
while (imp)
|
||||
{
|
||||
if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
|
||||
return TRUE;
|
||||
if (imp->iter_info)
|
||||
{
|
||||
const pixman_iter_info_t *info;
|
||||
|
||||
imp = imp->fallback;
|
||||
for (info = imp->iter_info; info->format != PIXMAN_null; ++info)
|
||||
{
|
||||
if ((info->format == PIXMAN_any || info->format == format) &&
|
||||
(info->image_flags & image_flags) == info->image_flags &&
|
||||
(info->iter_flags & iter_flags) == info->iter_flags)
|
||||
{
|
||||
iter->get_scanline = info->get_scanline;
|
||||
iter->write_back = info->write_back;
|
||||
|
||||
if (info->initializer)
|
||||
info->initializer (iter, info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
|
|
@ -384,6 +380,11 @@ _pixman_disabled (const char *name)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t empty_fast_path[] =
|
||||
{
|
||||
{ PIXMAN_OP_NONE }
|
||||
};
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_choose_implementation (void)
|
||||
{
|
||||
|
|
@ -401,5 +402,16 @@ _pixman_choose_implementation (void)
|
|||
|
||||
imp = _pixman_implementation_create_noop (imp);
|
||||
|
||||
if (_pixman_disabled ("wholeops"))
|
||||
{
|
||||
pixman_implementation_t *cur;
|
||||
|
||||
/* Disable all whole-operation paths except the general one,
|
||||
* so that optimized iterators are used as much as possible.
|
||||
*/
|
||||
for (cur = imp; cur->fallback; cur = cur->fallback)
|
||||
cur->fast_paths = empty_fast_path;
|
||||
}
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,34 +173,6 @@ bilinear_interpolation (uint32_t tl, uint32_t tr,
|
|||
|
||||
#else
|
||||
|
||||
#ifdef LOW_QUALITY_INTERPOLATION
|
||||
/* Based on Filter_32_opaque_portable from Skia */
|
||||
static force_inline uint32_t
|
||||
bilinear_interpolation(uint32_t a00, uint32_t a01,
|
||||
uint32_t a10, uint32_t a11,
|
||||
int x, int y)
|
||||
{
|
||||
int xy = x * y;
|
||||
static const uint32_t mask = 0xff00ff;
|
||||
|
||||
int scale = 256 - 16*y - 16*x + xy;
|
||||
uint32_t lo = (a00 & mask) * scale;
|
||||
uint32_t hi = ((a00 >> 8) & mask) * scale;
|
||||
|
||||
scale = 16*x - xy;
|
||||
lo += (a01 & mask) * scale;
|
||||
hi += ((a01 >> 8) & mask) * scale;
|
||||
|
||||
scale = 16*y - xy;
|
||||
lo += (a10 & mask) * scale;
|
||||
hi += ((a10 >> 8) & mask) * scale;
|
||||
|
||||
lo += (a11 & mask) * xy;
|
||||
hi += ((a11 >> 8) & mask) * xy;
|
||||
|
||||
return ((lo >> 8) & mask) | (hi & ~mask);
|
||||
}
|
||||
#else
|
||||
static force_inline uint32_t
|
||||
bilinear_interpolation (uint32_t tl, uint32_t tr,
|
||||
uint32_t bl, uint32_t br,
|
||||
|
|
@ -246,10 +218,35 @@ bilinear_interpolation (uint32_t tl, uint32_t tr,
|
|||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // BILINEAR_INTERPOLATION_BITS <= 4
|
||||
|
||||
static force_inline argb_t
|
||||
bilinear_interpolation_float (argb_t tl, argb_t tr,
|
||||
argb_t bl, argb_t br,
|
||||
float distx, float disty)
|
||||
{
|
||||
float distxy, distxiy, distixy, distixiy;
|
||||
argb_t r;
|
||||
|
||||
distxy = distx * disty;
|
||||
distxiy = distx * (1.f - disty);
|
||||
distixy = (1.f - distx) * disty;
|
||||
distixiy = (1.f - distx) * (1.f - disty);
|
||||
|
||||
r.a = tl.a * distixiy + tr.a * distxiy +
|
||||
bl.a * distixy + br.a * distxy;
|
||||
r.r = tl.r * distixiy + tr.r * distxiy +
|
||||
bl.r * distixy + br.r * distxy;
|
||||
r.g = tl.g * distixiy + tr.g * distxiy +
|
||||
bl.g * distixy + br.g * distxy;
|
||||
r.b = tl.b * distixiy + tr.b * distxiy +
|
||||
bl.b * distixy + br.b * distxy;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* For each scanline fetched from source image with PAD repeat:
|
||||
* - calculate how many pixels need to be padded on the left side
|
||||
|
|
@ -775,7 +772,8 @@ fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp,
|
|||
#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func)
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func), \
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (op,s,d,func)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -852,38 +850,8 @@ bilinear_pad_repeat_get_scanline_bounds (int32_t source_image_width,
|
|||
* with 8-bit SIMD multiplication instructions for 8-bit interpolation
|
||||
* precision.
|
||||
*/
|
||||
|
||||
/* Replace a single "scanline_func" with "fetch_func" & "op_func" to allow optional
|
||||
* two stage processing (bilinear fetch to a temp buffer, followed by unscaled
|
||||
* combine), "op_func" may be NULL, in this case we keep old behavior.
|
||||
* This is ugly and gcc issues some warnings, but works.
|
||||
*
|
||||
* An advice: clang has much better error reporting than gcc for deeply nested macros.
|
||||
*/
|
||||
|
||||
#define scanline_func(dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buf, mask, src_top, src_bottom, width, \
|
||||
weight_top, weight_bottom, vx, unit_x, max_vx, zero_src) \
|
||||
do { \
|
||||
if (op_func != NULL) \
|
||||
{ \
|
||||
fetch_func ((void *)scanline_buf, (mask), (src_top), (src_bottom), (width), \
|
||||
(weight_top), (weight_bottom), (vx), (unit_x), (max_vx), (zero_src)); \
|
||||
((void (*)(dst_type_t *, const mask_type_t *, const src_type_t *, int)) op_func)\
|
||||
((dst), (mask), (src_type_t *)scanline_buf, (width)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fetch_func ((void*)(dst), (mask), (src_top), (src_bottom), (width), (weight_top), \
|
||||
(weight_bottom), (vx), (unit_x), (max_vx), (zero_src)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define SCANLINE_BUFFER_LENGTH 3072
|
||||
|
||||
#define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, fetch_func, op_func, src_type_t, \
|
||||
mask_type_t, dst_type_t, repeat_mode, flags) \
|
||||
#define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \
|
||||
dst_type_t, repeat_mode, flags) \
|
||||
static void \
|
||||
fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, \
|
||||
pixman_composite_info_t *info) \
|
||||
|
|
@ -908,9 +876,6 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
pixman_fixed_t src_width_fixed; \
|
||||
int max_x; \
|
||||
pixman_bool_t need_src_extension; \
|
||||
\
|
||||
uint64_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH]; \
|
||||
uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; \
|
||||
\
|
||||
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type_t, dst_stride, dst_line, 1); \
|
||||
if (flags & FLAG_HAVE_SOLID_MASK) \
|
||||
|
|
@ -983,14 +948,6 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
\
|
||||
src_width_fixed = pixman_int_to_fixed (src_width); \
|
||||
} \
|
||||
\
|
||||
if (op_func != NULL && width * sizeof(src_type_t) > sizeof(stack_scanline_buffer)) \
|
||||
{ \
|
||||
scanline_buffer = pixman_malloc_ab (width, sizeof(src_type_t)); \
|
||||
\
|
||||
if (!scanline_buffer) \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
while (--height >= 0) \
|
||||
{ \
|
||||
|
|
@ -1033,18 +990,16 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
{ \
|
||||
buf1[0] = buf1[1] = src1[0]; \
|
||||
buf2[0] = buf2[1] = src2[0]; \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, buf1, buf2, left_pad, weight1, weight2, \
|
||||
0, 0, 0, FALSE); \
|
||||
scanline_func (dst, mask, \
|
||||
buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, FALSE); \
|
||||
dst += left_pad; \
|
||||
if (flags & FLAG_HAVE_NON_SOLID_MASK) \
|
||||
mask += left_pad; \
|
||||
} \
|
||||
if (width > 0) \
|
||||
{ \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, src1, src2, width, weight1, weight2, \
|
||||
vx, unit_x, 0, FALSE); \
|
||||
scanline_func (dst, mask, \
|
||||
src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \
|
||||
dst += width; \
|
||||
if (flags & FLAG_HAVE_NON_SOLID_MASK) \
|
||||
mask += width; \
|
||||
|
|
@ -1053,9 +1008,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
{ \
|
||||
buf1[0] = buf1[1] = src1[src_image->bits.width - 1]; \
|
||||
buf2[0] = buf2[1] = src2[src_image->bits.width - 1]; \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, buf1, buf2, right_pad, weight1, weight2, \
|
||||
0, 0, 0, FALSE); \
|
||||
scanline_func (dst, mask, \
|
||||
buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, FALSE); \
|
||||
} \
|
||||
} \
|
||||
else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \
|
||||
|
|
@ -1091,9 +1045,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
{ \
|
||||
buf1[0] = buf1[1] = 0; \
|
||||
buf2[0] = buf2[1] = 0; \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, buf1, buf2, left_pad, weight1, weight2, \
|
||||
0, 0, 0, TRUE); \
|
||||
scanline_func (dst, mask, \
|
||||
buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, TRUE); \
|
||||
dst += left_pad; \
|
||||
if (flags & FLAG_HAVE_NON_SOLID_MASK) \
|
||||
mask += left_pad; \
|
||||
|
|
@ -1104,8 +1057,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
buf1[1] = src1[0]; \
|
||||
buf2[0] = 0; \
|
||||
buf2[1] = src2[0]; \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, buf1, buf2, left_tz, weight1, weight2, \
|
||||
scanline_func (dst, mask, \
|
||||
buf1, buf2, left_tz, weight1, weight2, \
|
||||
pixman_fixed_frac (vx), unit_x, 0, FALSE); \
|
||||
dst += left_tz; \
|
||||
if (flags & FLAG_HAVE_NON_SOLID_MASK) \
|
||||
|
|
@ -1114,9 +1067,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
} \
|
||||
if (width > 0) \
|
||||
{ \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, src1, src2, width, weight1, weight2, \
|
||||
vx, unit_x, 0, FALSE); \
|
||||
scanline_func (dst, mask, \
|
||||
src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \
|
||||
dst += width; \
|
||||
if (flags & FLAG_HAVE_NON_SOLID_MASK) \
|
||||
mask += width; \
|
||||
|
|
@ -1128,8 +1080,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
buf1[1] = 0; \
|
||||
buf2[0] = src2[src_image->bits.width - 1]; \
|
||||
buf2[1] = 0; \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, buf1, buf2, right_tz, weight1, weight2, \
|
||||
scanline_func (dst, mask, \
|
||||
buf1, buf2, right_tz, weight1, weight2, \
|
||||
pixman_fixed_frac (vx), unit_x, 0, FALSE); \
|
||||
dst += right_tz; \
|
||||
if (flags & FLAG_HAVE_NON_SOLID_MASK) \
|
||||
|
|
@ -1139,9 +1091,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
{ \
|
||||
buf1[0] = buf1[1] = 0; \
|
||||
buf2[0] = buf2[1] = 0; \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, buf1, buf2, right_pad, weight1, weight2, \
|
||||
0, 0, 0, TRUE); \
|
||||
scanline_func (dst, mask, \
|
||||
buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, TRUE); \
|
||||
} \
|
||||
} \
|
||||
else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \
|
||||
|
|
@ -1203,8 +1154,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
if (num_pixels > width_remain) \
|
||||
num_pixels = width_remain; \
|
||||
\
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, \
|
||||
dst, scanline_buffer, mask, buf1, buf2, num_pixels, \
|
||||
scanline_func (dst, mask, buf1, buf2, num_pixels, \
|
||||
weight1, weight2, pixman_fixed_frac(vx), \
|
||||
unit_x, src_width_fixed, FALSE); \
|
||||
\
|
||||
|
|
@ -1233,10 +1183,8 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
if (num_pixels > width_remain) \
|
||||
num_pixels = width_remain; \
|
||||
\
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, \
|
||||
dst, scanline_buffer, mask, src_line_top, src_line_bottom, \
|
||||
num_pixels, weight1, weight2, vx, unit_x, src_width_fixed, \
|
||||
FALSE); \
|
||||
scanline_func (dst, mask, src_line_top, src_line_bottom, num_pixels, \
|
||||
weight1, weight2, vx, unit_x, src_width_fixed, FALSE); \
|
||||
\
|
||||
width_remain -= num_pixels; \
|
||||
vx += num_pixels * unit_x; \
|
||||
|
|
@ -1249,21 +1197,17 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
|
|||
} \
|
||||
else \
|
||||
{ \
|
||||
scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \
|
||||
scanline_buffer, mask, \
|
||||
src_first_line + src_stride * y1, \
|
||||
scanline_func (dst, mask, src_first_line + src_stride * y1, \
|
||||
src_first_line + src_stride * y2, width, \
|
||||
weight1, weight2, vx, unit_x, max_vx, FALSE); \
|
||||
} \
|
||||
} \
|
||||
if (scanline_buffer != (uint8_t *) stack_scanline_buffer) \
|
||||
free (scanline_buffer); \
|
||||
}
|
||||
|
||||
/* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */
|
||||
#define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, fetch_func, op_func, src_type_t, mask_type_t,\
|
||||
#define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \
|
||||
dst_type_t, repeat_mode, flags) \
|
||||
FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, fetch_func, op_func, src_type_t, mask_type_t,\
|
||||
FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t,\
|
||||
dst_type_t, repeat_mode, flags)
|
||||
|
||||
#define SCALED_BILINEAR_FLAGS \
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include "pixman-dither.h"
|
||||
|
||||
static pixman_bool_t
|
||||
linear_gradient_is_horizontal (pixman_image_t *image,
|
||||
int x,
|
||||
|
|
@ -91,8 +89,11 @@ linear_gradient_is_horizontal (pixman_image_t *image,
|
|||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_narrow (pixman_iter_t *iter,
|
||||
const uint32_t *mask)
|
||||
linear_get_scanline (pixman_iter_t *iter,
|
||||
const uint32_t *mask,
|
||||
int Bpp,
|
||||
pixman_gradient_walker_write_t write_pixel,
|
||||
pixman_gradient_walker_fill_t fill_pixel)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
|
|
@ -105,7 +106,7 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
pixman_fixed_48_16_t dx, dy;
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
uint32_t *end = buffer + width * (Bpp / 4);
|
||||
pixman_gradient_walker_t walker;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
|
@ -139,7 +140,7 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
if (l == 0 || unit.vector[2] == 0)
|
||||
{
|
||||
/* affine transformation only */
|
||||
pixman_fixed_32_32_t t, next_inc;
|
||||
pixman_fixed_32_32_t t, next_inc;
|
||||
double inc;
|
||||
|
||||
if (l == 0 || v.vector[2] == 0)
|
||||
|
|
@ -154,7 +155,7 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
|
||||
}
|
||||
|
|
@ -162,11 +163,7 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
|
||||
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
|
||||
{
|
||||
register uint32_t color;
|
||||
|
||||
color = _pixman_gradient_walker_pixel (&walker, t);
|
||||
while (buffer < end)
|
||||
*buffer++ = color;
|
||||
fill_pixel (&walker, t, buffer, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -177,12 +174,11 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = _pixman_gradient_walker_pixel (&walker,
|
||||
t + next_inc);
|
||||
write_pixel (&walker, t + next_inc, buffer);
|
||||
}
|
||||
i++;
|
||||
next_inc = inc * i;
|
||||
buffer++;
|
||||
buffer += (Bpp / 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -204,14 +200,14 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
}
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (&walker, t);
|
||||
write_pixel (&walker, t, buffer);
|
||||
}
|
||||
|
||||
++buffer;
|
||||
buffer += (Bpp / 4);
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
|
|
@ -225,176 +221,30 @@ linear_get_scanline_narrow (pixman_iter_t *iter,
|
|||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_16 (pixman_iter_t *iter,
|
||||
const uint32_t *mask)
|
||||
linear_get_scanline_narrow (pixman_iter_t *iter,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint16_t * buffer = (uint16_t*)iter->buffer;
|
||||
pixman_bool_t toggle = ((x ^ y) & 1);
|
||||
|
||||
pixman_vector_t v, unit;
|
||||
pixman_fixed_32_32_t l;
|
||||
pixman_fixed_48_16_t dx, dy;
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
uint16_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
dx = linear->p2.x - linear->p1.x;
|
||||
dy = linear->p2.y - linear->p1.y;
|
||||
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0 || unit.vector[2] == 0)
|
||||
{
|
||||
/* affine transformation only */
|
||||
pixman_fixed_32_32_t t, next_inc;
|
||||
double inc;
|
||||
|
||||
if (l == 0 || v.vector[2] == 0)
|
||||
{
|
||||
t = 0;
|
||||
inc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
|
||||
}
|
||||
next_inc = 0;
|
||||
|
||||
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
|
||||
{
|
||||
register uint32_t color;
|
||||
uint16_t dither_diff;
|
||||
uint16_t color16;
|
||||
uint16_t color16b;
|
||||
|
||||
color = _pixman_gradient_walker_pixel (&walker, t);
|
||||
color16 = dither_8888_to_0565(color, toggle);
|
||||
color16b = dither_8888_to_0565(color, toggle^1);
|
||||
// compute the difference
|
||||
dither_diff = color16 ^ color16b;
|
||||
while (buffer < end) {
|
||||
*buffer++ = color16;
|
||||
// use dither_diff to toggle between color16 and color16b
|
||||
color16 ^= dither_diff;
|
||||
toggle ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker,
|
||||
t + next_inc),
|
||||
toggle);
|
||||
}
|
||||
toggle ^= 1;
|
||||
i++;
|
||||
next_inc = inc * i;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective transformation */
|
||||
double t;
|
||||
|
||||
t = 0;
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
}
|
||||
|
||||
*buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t),
|
||||
toggle);
|
||||
}
|
||||
toggle ^= 1;
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
|
||||
return iter->buffer;
|
||||
return linear_get_scanline (iter, mask, 4,
|
||||
_pixman_gradient_walker_write_narrow,
|
||||
_pixman_gradient_walker_fill_narrow);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
return linear_get_scanline (iter, NULL, 16,
|
||||
_pixman_gradient_walker_write_wide,
|
||||
_pixman_gradient_walker_fill_wide);
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
// XXX: we can't use this optimization when dithering
|
||||
if (0 && linear_gradient_is_horizontal (
|
||||
if (linear_gradient_is_horizontal (
|
||||
iter->image, iter->x, iter->y, iter->width, iter->height))
|
||||
{
|
||||
if (iter->iter_flags & ITER_16)
|
||||
linear_get_scanline_16 (iter, NULL);
|
||||
else if (iter->iter_flags & ITER_NARROW)
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
linear_get_scanline_narrow (iter, NULL);
|
||||
else
|
||||
linear_get_scanline_wide (iter, NULL);
|
||||
|
|
@ -403,9 +253,7 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (iter->iter_flags & ITER_16)
|
||||
iter->get_scanline = linear_get_scanline_16;
|
||||
else if (iter->iter_flags & ITER_NARROW)
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = linear_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = linear_get_scanline_wide;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
static force_inline int
|
||||
count_leading_zeros (uint32_t x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
#ifdef HAVE_BUILTIN_CLZ
|
||||
return __builtin_clz (x);
|
||||
#else
|
||||
int n = 0;
|
||||
|
|
@ -273,7 +273,7 @@ pixman_transform_point_31_16 (const pixman_transform_t *t,
|
|||
{
|
||||
/* the divisor is small, we can actually keep all the bits */
|
||||
int64_t hi, rhi, lo, rlo;
|
||||
int64_t div = (divint << 16) + divfrac;
|
||||
int64_t div = ((uint64_t)divint << 16) + divfrac;
|
||||
|
||||
fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32);
|
||||
rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -26,7 +26,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Nemanja Lukic (nlukic@mips.com)
|
||||
* Author: Nemanja Lukic (nemanja.lukic@rt-rk.com)
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_MIPS_DSPR2_ASM_H
|
||||
|
|
@ -72,6 +72,7 @@
|
|||
#define LEAF_MIPS32R2(symbol) \
|
||||
.globl symbol; \
|
||||
.align 2; \
|
||||
.hidden symbol; \
|
||||
.type symbol, @function; \
|
||||
.ent symbol, 0; \
|
||||
symbol: .frame sp, 0, ra; \
|
||||
|
|
@ -354,17 +355,16 @@ LEAF_MIPS32R2(symbol) \
|
|||
out1_565, out2_565, \
|
||||
maskR, maskG, maskB, \
|
||||
scratch1, scratch2
|
||||
precrq.ph.w \scratch1, \in2_8888, \in1_8888
|
||||
precr_sra.ph.w \in2_8888, \in1_8888, 0
|
||||
shll.ph \scratch1, \scratch1, 8
|
||||
srl \in2_8888, \in2_8888, 3
|
||||
and \scratch2, \in2_8888, \maskB
|
||||
and \scratch1, \scratch1, \maskR
|
||||
srl \in2_8888, \in2_8888, 2
|
||||
and \out2_565, \in2_8888, \maskG
|
||||
or \out2_565, \out2_565, \scratch2
|
||||
or \out1_565, \out2_565, \scratch1
|
||||
srl \out2_565, \out1_565, 16
|
||||
precr.qb.ph \scratch1, \in2_8888, \in1_8888
|
||||
precrq.qb.ph \in2_8888, \in2_8888, \in1_8888
|
||||
and \out1_565, \scratch1, \maskR
|
||||
shrl.ph \scratch1, \scratch1, 3
|
||||
shll.ph \in2_8888, \in2_8888, 3
|
||||
and \scratch1, \scratch1, \maskB
|
||||
or \out1_565, \out1_565, \scratch1
|
||||
and \in2_8888, \in2_8888, \maskG
|
||||
or \out1_565, \out1_565, \in2_8888
|
||||
srl \out2_565, \out1_565, 16
|
||||
.endm
|
||||
|
||||
/*
|
||||
|
|
@ -587,6 +587,36 @@ LEAF_MIPS32R2(symbol) \
|
|||
addu_s.qb \out_8888, \out_8888, \s_8888
|
||||
.endm
|
||||
|
||||
/*
|
||||
* OVER operation on two a8r8g8b8 source pixels (s1_8888 and s2_8888) and two
|
||||
* a8r8g8b8 destination pixels (d1_8888 and d2_8888). It also requires maskLSR
|
||||
* needed for rounding process. maskLSR must have following value:
|
||||
* li maskLSR, 0x00ff00ff
|
||||
*/
|
||||
.macro OVER_2x8888_2x8888 s1_8888, \
|
||||
s2_8888, \
|
||||
d1_8888, \
|
||||
d2_8888, \
|
||||
out1_8888, \
|
||||
out2_8888, \
|
||||
maskLSR, \
|
||||
scratch1, scratch2, scratch3, \
|
||||
scratch4, scratch5, scratch6
|
||||
not \scratch1, \s1_8888
|
||||
srl \scratch1, \scratch1, 24
|
||||
not \scratch2, \s2_8888
|
||||
srl \scratch2, \scratch2, 24
|
||||
MIPS_2xUN8x4_MUL_2xUN8 \d1_8888, \d2_8888, \
|
||||
\scratch1, \scratch2, \
|
||||
\out1_8888, \out2_8888, \
|
||||
\maskLSR, \
|
||||
\scratch3, \scratch4, \scratch5, \
|
||||
\scratch6, \d1_8888, \d2_8888
|
||||
|
||||
addu_s.qb \out1_8888, \out1_8888, \s1_8888
|
||||
addu_s.qb \out2_8888, \out2_8888, \s2_8888
|
||||
.endm
|
||||
|
||||
.macro MIPS_UN8x4_MUL_UN8_ADD_UN8x4 s_8888, \
|
||||
m_8, \
|
||||
d_8888, \
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Nemanja Lukic (nlukic@mips.com)
|
||||
* Author: Nemanja Lukic (nemanja.lukic@rt-rk.com)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
@ -48,8 +48,20 @@ PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888,
|
|||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888,
|
||||
uint8_t, 3, uint8_t, 3)
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0888_8888_rev,
|
||||
uint8_t, 3, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0888_0565_rev,
|
||||
uint8_t, 3, uint16_t, 1)
|
||||
#endif
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_pixbuf_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_rpixbuf_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_8888,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_0565,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8888_8888,
|
||||
|
|
@ -67,6 +79,8 @@ PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca,
|
|||
uint32_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_0565_ca,
|
||||
uint32_t, 1, uint16_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8,
|
||||
uint8_t, 1, uint8_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888,
|
||||
uint8_t, 1, uint32_t, 1)
|
||||
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565,
|
||||
|
|
@ -111,6 +125,13 @@ PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_0565_8_0565, uint16_t, 1,
|
|||
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8888_8888, uint32_t, 1,
|
||||
uint32_t, 1, uint32_t, 1)
|
||||
|
||||
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST (8888_8888, OVER,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST (8888_0565, OVER,
|
||||
uint32_t, uint16_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST (0565_8888, SRC,
|
||||
uint16_t, uint32_t)
|
||||
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC,
|
||||
uint32_t, uint32_t)
|
||||
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC,
|
||||
|
|
@ -278,6 +299,14 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, mips_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, mips_composite_src_x888_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, mips_composite_src_0888_0888),
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, mips_composite_src_0888_8888_rev),
|
||||
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, mips_composite_src_0888_0565_rev),
|
||||
#endif
|
||||
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, mips_composite_src_pixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, mips_composite_src_rpixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, mips_composite_src_rpixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, mips_composite_src_pixbuf_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mips_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mips_composite_src_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mips_composite_src_n_8_8888),
|
||||
|
|
@ -290,6 +319,7 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, mips_composite_over_n_8888_8888_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, mips_composite_over_n_8888_0565_ca),
|
||||
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, mips_composite_over_n_8888_0565_ca),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, mips_composite_over_n_8_8),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, mips_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, mips_composite_over_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, mips_composite_over_n_8_8888),
|
||||
|
|
@ -318,6 +348,8 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mips_composite_over_8888_8888),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, mips_composite_over_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, mips_composite_over_8888_0565),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mips_composite_add_n_8_8),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, mips_composite_add_n_8_8888),
|
||||
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, mips_composite_add_n_8_8888),
|
||||
|
|
@ -340,11 +372,27 @@ static const pixman_fast_path_t mips_dspr2_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, mips_composite_over_reverse_n_8888),
|
||||
PIXMAN_STD_FAST_PATH (IN, solid, null, a8, mips_composite_in_n_8),
|
||||
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8r8g8b8, r5g6b5, mips_8888_8_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8b8g8r8, b5g6r5, mips_8888_8_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8888),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mips_8888_8888),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8888),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mips_8888_8888),
|
||||
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, mips_0565_8_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, mips_0565_8_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, mips_8888_0565),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, mips_8888_0565),
|
||||
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, mips_0565_8888),
|
||||
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888),
|
||||
/* Note: NONE repeat is not supported yet */
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, mips_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, mips_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, r5g6b5, a8r8g8b8, mips_0565_8888),
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, b5g6r5, a8b8g8r8, mips_0565_8888),
|
||||
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8r8g8b8, r5g6b5, mips_8888_8_0565),
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8b8g8r8, b5g6r5, mips_8888_8_0565),
|
||||
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, mips_0565_8_0565),
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, mips_0565_8_0565),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Nemanja Lukic (nlukic@mips.com)
|
||||
* Author: Nemanja Lukic (nemanja.lukic@rt-rk.com)
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_MIPS_DSPR2_H
|
||||
|
|
@ -246,6 +246,48 @@ mips_composite_##name (pixman_implementation_t *imp, \
|
|||
} \
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST(name, op, \
|
||||
src_type, dst_type) \
|
||||
void \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips ( \
|
||||
dst_type * dst, \
|
||||
const src_type * src, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x); \
|
||||
\
|
||||
static force_inline void \
|
||||
scaled_nearest_scanline_mips_##name##_##op (dst_type * pd, \
|
||||
const src_type * ps, \
|
||||
int32_t w, \
|
||||
pixman_fixed_t vx, \
|
||||
pixman_fixed_t unit_x, \
|
||||
pixman_fixed_t max_vx, \
|
||||
pixman_bool_t zero_src) \
|
||||
{ \
|
||||
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips (pd, ps, w, \
|
||||
vx, unit_x); \
|
||||
} \
|
||||
\
|
||||
FAST_NEAREST_MAINLOOP (mips_##name##_cover_##op, \
|
||||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, dst_type, COVER) \
|
||||
FAST_NEAREST_MAINLOOP (mips_##name##_none_##op, \
|
||||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, dst_type, NONE) \
|
||||
FAST_NEAREST_MAINLOOP (mips_##name##_pad_##op, \
|
||||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, dst_type, PAD)
|
||||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func)
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST(flags, name, op, \
|
||||
|
|
@ -286,12 +328,6 @@ FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_pad_##op, \
|
|||
scaled_nearest_scanline_mips_##name##_##op, \
|
||||
src_type, uint8_t, dst_type, PAD, TRUE, FALSE)
|
||||
|
||||
/* Provide entries for the fast path table */
|
||||
#define PIXMAN_MIPS_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \
|
||||
SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op, \
|
||||
|
|
|
|||
|
|
@ -44,8 +44,6 @@
|
|||
#include "pixman-combine32.h"
|
||||
#include "pixman-inlines.h"
|
||||
|
||||
#define no_vERBOSE
|
||||
|
||||
#ifdef VERBOSE
|
||||
#define CHECKPOINT() error_f ("at %s %d\n", __FUNCTION__, __LINE__)
|
||||
#else
|
||||
|
|
@ -91,21 +89,7 @@ _mm_mulhi_pu16 (__m64 __A, __m64 __B)
|
|||
return __A;
|
||||
}
|
||||
|
||||
# ifdef __OPTIMIZE__
|
||||
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_shuffle_pi16 (__m64 __A, int8_t const __N)
|
||||
{
|
||||
__m64 ret;
|
||||
|
||||
asm ("pshufw %2, %1, %0\n\t"
|
||||
: "=y" (ret)
|
||||
: "y" (__A), "K" (__N)
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
# else
|
||||
# define _mm_shuffle_pi16(A, N) \
|
||||
# define _mm_shuffle_pi16(A, N) \
|
||||
({ \
|
||||
__m64 ret; \
|
||||
\
|
||||
|
|
@ -116,7 +100,6 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N)
|
|||
\
|
||||
ret; \
|
||||
})
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
@ -303,6 +286,29 @@ negate (__m64 mask)
|
|||
return _mm_xor_si64 (mask, MC (4x00ff));
|
||||
}
|
||||
|
||||
/* Computes the product of two unsigned fixed-point 8-bit values from 0 to 1
|
||||
* and maps its result to the same range.
|
||||
*
|
||||
* Jim Blinn gives multiple ways to compute this in "Jim Blinn's Corner:
|
||||
* Notation, Notation, Notation", the first of which is
|
||||
*
|
||||
* prod(a, b) = (a * b + 128) / 255.
|
||||
*
|
||||
* By approximating the division by 255 as 257/65536 it can be replaced by a
|
||||
* multiply and a right shift. This is the implementation that we use in
|
||||
* pix_multiply(), but we _mm_mulhi_pu16() by 257 (part of SSE1 or Extended
|
||||
* 3DNow!, and unavailable at the time of the book's publication) to perform
|
||||
* the multiplication and right shift in a single operation.
|
||||
*
|
||||
* prod(a, b) = ((a * b + 128) * 257) >> 16.
|
||||
*
|
||||
* A third way (how pix_multiply() was implemented prior to 14208344) exists
|
||||
* also that performs the multiplication by 257 with adds and shifts.
|
||||
*
|
||||
* Where temp = a * b + 128
|
||||
*
|
||||
* prod(a, b) = (temp + (temp >> 8)) >> 8.
|
||||
*/
|
||||
static force_inline __m64
|
||||
pix_multiply (__m64 a, __m64 b)
|
||||
{
|
||||
|
|
@ -381,8 +387,10 @@ in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest)
|
|||
static force_inline __m64 ldq_u(__m64 *p)
|
||||
{
|
||||
#ifdef USE_X86_MMX
|
||||
/* x86's alignment restrictions are very relaxed. */
|
||||
return *(__m64 *)p;
|
||||
/* x86's alignment restrictions are very relaxed, but that's no excuse */
|
||||
__m64 r;
|
||||
memcpy(&r, p, sizeof(__m64));
|
||||
return r;
|
||||
#elif defined USE_ARM_IWMMXT
|
||||
int align = (uintptr_t)p & 7;
|
||||
__m64 *aligned_p;
|
||||
|
|
@ -401,7 +409,9 @@ static force_inline uint32_t ldl_u(const uint32_t *p)
|
|||
{
|
||||
#ifdef USE_X86_MMX
|
||||
/* x86's alignment restrictions are very relaxed. */
|
||||
return *p;
|
||||
uint32_t r;
|
||||
memcpy(&r, p, sizeof(uint32_t));
|
||||
return r;
|
||||
#else
|
||||
struct __una_u32 { uint32_t x __attribute__((packed)); };
|
||||
const struct __una_u32 *ptr = (const struct __una_u32 *) p;
|
||||
|
|
@ -3534,13 +3544,111 @@ mmx_composite_over_reverse_n_8888 (pixman_implementation_t *imp,
|
|||
_mm_empty ();
|
||||
}
|
||||
|
||||
static force_inline void
|
||||
scaled_nearest_scanline_mmx_8888_8888_OVER (uint32_t* pd,
|
||||
const uint32_t* ps,
|
||||
int32_t w,
|
||||
pixman_fixed_t vx,
|
||||
pixman_fixed_t unit_x,
|
||||
pixman_fixed_t src_width_fixed,
|
||||
pixman_bool_t fully_transparent_src)
|
||||
{
|
||||
if (fully_transparent_src)
|
||||
return;
|
||||
|
||||
while (w)
|
||||
{
|
||||
__m64 d = load (pd);
|
||||
__m64 s = load (ps + pixman_fixed_to_int (vx));
|
||||
vx += unit_x;
|
||||
while (vx >= 0)
|
||||
vx -= src_width_fixed;
|
||||
|
||||
store8888 (pd, core_combine_over_u_pixel_mmx (s, d));
|
||||
pd++;
|
||||
|
||||
w--;
|
||||
}
|
||||
|
||||
_mm_empty ();
|
||||
}
|
||||
|
||||
FAST_NEAREST_MAINLOOP (mmx_8888_8888_cover_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_8888_OVER,
|
||||
uint32_t, uint32_t, COVER)
|
||||
FAST_NEAREST_MAINLOOP (mmx_8888_8888_none_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_8888_OVER,
|
||||
uint32_t, uint32_t, NONE)
|
||||
FAST_NEAREST_MAINLOOP (mmx_8888_8888_pad_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_8888_OVER,
|
||||
uint32_t, uint32_t, PAD)
|
||||
FAST_NEAREST_MAINLOOP (mmx_8888_8888_normal_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_8888_OVER,
|
||||
uint32_t, uint32_t, NORMAL)
|
||||
|
||||
static force_inline void
|
||||
scaled_nearest_scanline_mmx_8888_n_8888_OVER (const uint32_t * mask,
|
||||
uint32_t * dst,
|
||||
const uint32_t * src,
|
||||
int32_t w,
|
||||
pixman_fixed_t vx,
|
||||
pixman_fixed_t unit_x,
|
||||
pixman_fixed_t src_width_fixed,
|
||||
pixman_bool_t zero_src)
|
||||
{
|
||||
__m64 mm_mask;
|
||||
|
||||
if (zero_src || (*mask >> 24) == 0)
|
||||
{
|
||||
/* A workaround for https://gcc.gnu.org/PR47759 */
|
||||
_mm_empty ();
|
||||
return;
|
||||
}
|
||||
|
||||
mm_mask = expand_alpha (load8888 (mask));
|
||||
|
||||
while (w)
|
||||
{
|
||||
uint32_t s = *(src + pixman_fixed_to_int (vx));
|
||||
vx += unit_x;
|
||||
while (vx >= 0)
|
||||
vx -= src_width_fixed;
|
||||
|
||||
if (s)
|
||||
{
|
||||
__m64 ms = load8888 (&s);
|
||||
__m64 alpha = expand_alpha (ms);
|
||||
__m64 dest = load8888 (dst);
|
||||
|
||||
store8888 (dst, (in_over (ms, alpha, mm_mask, dest)));
|
||||
}
|
||||
|
||||
dst++;
|
||||
w--;
|
||||
}
|
||||
|
||||
_mm_empty ();
|
||||
}
|
||||
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_cover_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_n_8888_OVER,
|
||||
uint32_t, uint32_t, uint32_t, COVER, TRUE, TRUE)
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_pad_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_n_8888_OVER,
|
||||
uint32_t, uint32_t, uint32_t, PAD, TRUE, TRUE)
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_none_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_n_8888_OVER,
|
||||
uint32_t, uint32_t, uint32_t, NONE, TRUE, TRUE)
|
||||
FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_normal_OVER,
|
||||
scaled_nearest_scanline_mmx_8888_n_8888_OVER,
|
||||
uint32_t, uint32_t, uint32_t, NORMAL, TRUE, TRUE)
|
||||
|
||||
#define BSHIFT ((1 << BILINEAR_INTERPOLATION_BITS))
|
||||
#define BMSK (BSHIFT - 1)
|
||||
|
||||
#define BILINEAR_DECLARE_VARIABLES \
|
||||
const __m64 mm_wt = _mm_set_pi16 (wt, wt, wt, wt); \
|
||||
const __m64 mm_wb = _mm_set_pi16 (wb, wb, wb, wb); \
|
||||
const __m64 mm_BSHIFT = _mm_set_pi16 (BSHIFT, BSHIFT, BSHIFT, BSHIFT); \
|
||||
const __m64 mm_addc7 = _mm_set_pi16 (0, 1, 0, 1); \
|
||||
const __m64 mm_xorc7 = _mm_set_pi16 (0, BMSK, 0, BMSK); \
|
||||
const __m64 mm_ux = _mm_set_pi16 (unit_x, unit_x, unit_x, unit_x); \
|
||||
|
|
@ -3559,36 +3667,16 @@ do { \
|
|||
__m64 b_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (b, mm_zero), mm_wb); \
|
||||
__m64 hi = _mm_add_pi16 (t_hi, b_hi); \
|
||||
__m64 lo = _mm_add_pi16 (t_lo, b_lo); \
|
||||
vx += unit_x; \
|
||||
if (BILINEAR_INTERPOLATION_BITS < 8) \
|
||||
{ \
|
||||
/* calculate horizontal weights */ \
|
||||
__m64 mm_wh = _mm_add_pi16 (mm_addc7, _mm_xor_si64 (mm_xorc7, \
|
||||
/* calculate horizontal weights */ \
|
||||
__m64 mm_wh = _mm_add_pi16 (mm_addc7, _mm_xor_si64 (mm_xorc7, \
|
||||
_mm_srli_pi16 (mm_x, \
|
||||
16 - BILINEAR_INTERPOLATION_BITS))); \
|
||||
/* horizontal interpolation */ \
|
||||
__m64 p = _mm_unpacklo_pi16 (lo, hi); \
|
||||
__m64 q = _mm_unpackhi_pi16 (lo, hi); \
|
||||
lo = _mm_madd_pi16 (p, mm_wh); \
|
||||
hi = _mm_madd_pi16 (q, mm_wh); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* calculate horizontal weights */ \
|
||||
__m64 mm_wh_lo = _mm_sub_pi16 (mm_BSHIFT, _mm_srli_pi16 (mm_x, \
|
||||
16 - BILINEAR_INTERPOLATION_BITS)); \
|
||||
__m64 mm_wh_hi = _mm_srli_pi16 (mm_x, \
|
||||
16 - BILINEAR_INTERPOLATION_BITS); \
|
||||
/* horizontal interpolation */ \
|
||||
__m64 mm_lo_lo = _mm_mullo_pi16 (lo, mm_wh_lo); \
|
||||
__m64 mm_lo_hi = _mm_mullo_pi16 (hi, mm_wh_hi); \
|
||||
__m64 mm_hi_lo = _mm_mulhi_pu16 (lo, mm_wh_lo); \
|
||||
__m64 mm_hi_hi = _mm_mulhi_pu16 (hi, mm_wh_hi); \
|
||||
lo = _mm_add_pi32 (_mm_unpacklo_pi16 (mm_lo_lo, mm_hi_lo), \
|
||||
_mm_unpacklo_pi16 (mm_lo_hi, mm_hi_hi)); \
|
||||
hi = _mm_add_pi32 (_mm_unpackhi_pi16 (mm_lo_lo, mm_hi_lo), \
|
||||
_mm_unpackhi_pi16 (mm_lo_hi, mm_hi_hi)); \
|
||||
} \
|
||||
/* horizontal interpolation */ \
|
||||
__m64 p = _mm_unpacklo_pi16 (lo, hi); \
|
||||
__m64 q = _mm_unpackhi_pi16 (lo, hi); \
|
||||
vx += unit_x; \
|
||||
lo = _mm_madd_pi16 (p, mm_wh); \
|
||||
hi = _mm_madd_pi16 (q, mm_wh); \
|
||||
mm_x = _mm_add_pi16 (mm_x, mm_ux); \
|
||||
/* shift and pack the result */ \
|
||||
hi = _mm_srli_pi32 (hi, BILINEAR_INTERPOLATION_BITS * 2); \
|
||||
|
|
@ -3866,7 +3954,7 @@ mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask)
|
|||
|
||||
while (w && (((uintptr_t)dst) & 15))
|
||||
{
|
||||
*dst++ = *(src++) << 24;
|
||||
*dst++ = (uint32_t)*(src++) << 24;
|
||||
w--;
|
||||
}
|
||||
|
||||
|
|
@ -3893,7 +3981,7 @@ mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask)
|
|||
|
||||
while (w)
|
||||
{
|
||||
*dst++ = *(src++) << 24;
|
||||
*dst++ = (uint32_t)*(src++) << 24;
|
||||
w--;
|
||||
}
|
||||
|
||||
|
|
@ -3901,52 +3989,23 @@ mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask)
|
|||
return iter->buffer;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixman_format_code_t format;
|
||||
pixman_iter_get_scanline_t get_scanline;
|
||||
} fetcher_info_t;
|
||||
|
||||
static const fetcher_info_t fetchers[] =
|
||||
{
|
||||
{ PIXMAN_x8r8g8b8, mmx_fetch_x8r8g8b8 },
|
||||
{ PIXMAN_r5g6b5, mmx_fetch_r5g6b5 },
|
||||
{ PIXMAN_a8, mmx_fetch_a8 },
|
||||
{ PIXMAN_null }
|
||||
};
|
||||
|
||||
static pixman_bool_t
|
||||
mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
#define FLAGS \
|
||||
#define IMAGE_FLAGS \
|
||||
(FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \
|
||||
FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
|
||||
|
||||
if ((iter->iter_flags & ITER_NARROW) &&
|
||||
(iter->image_flags & FLAGS) == FLAGS)
|
||||
{
|
||||
const fetcher_info_t *f;
|
||||
|
||||
for (f = &fetchers[0]; f->format != PIXMAN_null; f++)
|
||||
{
|
||||
if (image->common.extended_format_code == f->format)
|
||||
{
|
||||
uint8_t *b = (uint8_t *)image->bits.bits;
|
||||
int s = image->bits.rowstride * 4;
|
||||
|
||||
iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8;
|
||||
iter->stride = s;
|
||||
|
||||
iter->get_scanline = f->get_scanline;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
static const pixman_iter_info_t mmx_iters[] =
|
||||
{
|
||||
{ PIXMAN_x8r8g8b8, IMAGE_FLAGS, ITER_NARROW,
|
||||
_pixman_iter_init_bits_stride, mmx_fetch_x8r8g8b8, NULL
|
||||
},
|
||||
{ PIXMAN_r5g6b5, IMAGE_FLAGS, ITER_NARROW,
|
||||
_pixman_iter_init_bits_stride, mmx_fetch_r5g6b5, NULL
|
||||
},
|
||||
{ PIXMAN_a8, IMAGE_FLAGS, ITER_NARROW,
|
||||
_pixman_iter_init_bits_stride, mmx_fetch_a8, NULL
|
||||
},
|
||||
{ PIXMAN_null },
|
||||
};
|
||||
|
||||
static const pixman_fast_path_t mmx_fast_paths[] =
|
||||
{
|
||||
|
|
@ -4024,6 +4083,16 @@ static const pixman_fast_path_t mmx_fast_paths[] =
|
|||
PIXMAN_STD_FAST_PATH (IN, a8, null, a8, mmx_composite_in_8_8 ),
|
||||
PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, mmx_composite_in_n_8_8 ),
|
||||
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8888 ),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ),
|
||||
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8888 ),
|
||||
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_n_8888 ),
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_n_8888 ),
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_n_8888 ),
|
||||
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_n_8888 ),
|
||||
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ),
|
||||
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mmx_8888_8888 ),
|
||||
|
|
@ -4076,7 +4145,7 @@ _pixman_implementation_create_mmx (pixman_implementation_t *fallback)
|
|||
imp->blt = mmx_blt;
|
||||
imp->fill = mmx_fill;
|
||||
|
||||
imp->src_iter_init = mmx_src_iter_init;
|
||||
imp->iter_info = mmx_iters;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,6 @@ noop_composite (pixman_implementation_t *imp,
|
|||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dest_write_back_direct (pixman_iter_t *iter)
|
||||
{
|
||||
iter->buffer += iter->image->bits.rowstride;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
noop_get_scanline (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
|
|
@ -53,110 +47,102 @@ noop_get_scanline (pixman_iter_t *iter, const uint32_t *mask)
|
|||
return result;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
return NULL;
|
||||
static void
|
||||
noop_init_solid_narrow (pixman_iter_t *iter,
|
||||
const pixman_iter_info_t *info)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
uint32_t *buffer = iter->buffer;
|
||||
uint32_t *end = buffer + iter->width;
|
||||
uint32_t color;
|
||||
|
||||
if (iter->image->type == SOLID)
|
||||
color = image->solid.color_32;
|
||||
else
|
||||
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
static void
|
||||
noop_init_solid_wide (pixman_iter_t *iter,
|
||||
const pixman_iter_info_t *info)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
argb_t *buffer = (argb_t *)iter->buffer;
|
||||
argb_t *end = buffer + iter->width;
|
||||
argb_t color;
|
||||
|
||||
if (iter->image->type == SOLID)
|
||||
color = image->solid.color_float;
|
||||
else
|
||||
color = image->bits.fetch_pixel_float (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
|
||||
static void
|
||||
noop_init_direct_buffer (pixman_iter_t *iter, const pixman_iter_info_t *info)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
#define FLAGS \
|
||||
(FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM)
|
||||
|
||||
if (!image)
|
||||
{
|
||||
iter->get_scanline = get_scanline_null;
|
||||
}
|
||||
else if ((iter->iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
|
||||
{
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else if (image->common.extended_format_code == PIXMAN_solid &&
|
||||
(iter->image->type == SOLID ||
|
||||
(iter->image_flags & FAST_PATH_NO_ALPHA_MAP)))
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
{
|
||||
uint32_t *buffer = iter->buffer;
|
||||
uint32_t *end = buffer + iter->width;
|
||||
uint32_t color;
|
||||
|
||||
if (image->type == SOLID)
|
||||
color = image->solid.color_32;
|
||||
else
|
||||
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
argb_t *buffer = (argb_t *)iter->buffer;
|
||||
argb_t *end = buffer + iter->width;
|
||||
argb_t color;
|
||||
|
||||
if (image->type == SOLID)
|
||||
color = image->solid.color_float;
|
||||
else
|
||||
color = image->bits.fetch_pixel_float (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else if (image->common.extended_format_code == PIXMAN_a8r8g8b8 &&
|
||||
(iter->iter_flags & ITER_NARROW) &&
|
||||
(iter->image_flags & FLAGS) == FLAGS &&
|
||||
iter->x >= 0 && iter->y >= 0 &&
|
||||
iter->x + iter->width <= image->bits.width &&
|
||||
iter->y + iter->height <= image->bits.height)
|
||||
{
|
||||
iter->buffer =
|
||||
image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
|
||||
iter->get_scanline = noop_get_scanline;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
iter->buffer =
|
||||
image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
static void
|
||||
dest_write_back_direct (pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
uint32_t image_flags = iter->image_flags;
|
||||
uint32_t iter_flags = iter->iter_flags;
|
||||
|
||||
if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS &&
|
||||
(iter_flags & ITER_NARROW) == ITER_NARROW &&
|
||||
((image->common.extended_format_code == PIXMAN_a8r8g8b8) ||
|
||||
(image->common.extended_format_code == PIXMAN_x8r8g8b8 &&
|
||||
(iter_flags & (ITER_LOCALIZED_ALPHA)))))
|
||||
{
|
||||
iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
iter->write_back = dest_write_back_direct;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
iter->buffer += iter->image->bits.rowstride;
|
||||
}
|
||||
|
||||
static const pixman_iter_info_t noop_iters[] =
|
||||
{
|
||||
/* Source iters */
|
||||
{ PIXMAN_any,
|
||||
0, ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_SRC,
|
||||
NULL,
|
||||
_pixman_iter_get_scanline_noop,
|
||||
NULL
|
||||
},
|
||||
{ PIXMAN_solid,
|
||||
FAST_PATH_NO_ALPHA_MAP, ITER_NARROW | ITER_SRC,
|
||||
noop_init_solid_narrow,
|
||||
_pixman_iter_get_scanline_noop,
|
||||
NULL,
|
||||
},
|
||||
{ PIXMAN_solid,
|
||||
FAST_PATH_NO_ALPHA_MAP, ITER_WIDE | ITER_SRC,
|
||||
noop_init_solid_wide,
|
||||
_pixman_iter_get_scanline_noop,
|
||||
NULL
|
||||
},
|
||||
{ PIXMAN_a8r8g8b8,
|
||||
FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |
|
||||
FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST,
|
||||
ITER_NARROW | ITER_SRC,
|
||||
noop_init_direct_buffer,
|
||||
noop_get_scanline,
|
||||
NULL
|
||||
},
|
||||
/* Dest iters */
|
||||
{ PIXMAN_a8r8g8b8,
|
||||
FAST_PATH_STD_DEST_FLAGS, ITER_NARROW | ITER_DEST,
|
||||
noop_init_direct_buffer,
|
||||
_pixman_iter_get_scanline_noop,
|
||||
dest_write_back_direct
|
||||
},
|
||||
{ PIXMAN_x8r8g8b8,
|
||||
FAST_PATH_STD_DEST_FLAGS, ITER_NARROW | ITER_DEST | ITER_LOCALIZED_ALPHA,
|
||||
noop_init_direct_buffer,
|
||||
_pixman_iter_get_scanline_noop,
|
||||
dest_write_back_direct
|
||||
},
|
||||
{ PIXMAN_null },
|
||||
};
|
||||
|
||||
static const pixman_fast_path_t noop_fast_paths[] =
|
||||
{
|
||||
{ PIXMAN_OP_DST, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, noop_composite },
|
||||
|
|
@ -169,8 +155,7 @@ _pixman_implementation_create_noop (pixman_implementation_t *fallback)
|
|||
pixman_implementation_t *imp =
|
||||
_pixman_implementation_create (fallback, noop_fast_paths);
|
||||
|
||||
imp->src_iter_init = noop_src_iter_init;
|
||||
imp->dest_iter_init = noop_dest_iter_init;
|
||||
imp->iter_info = noop_iters;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue